+Fri Jan 29 09:18:41 GMT 1999 Tony Gale <gale@gtk.org>
+
+ * docs/gtk_tut.sgml:
+ - New sections on the Fixed and Frame containers
+ - Rearrange the Containers section so the easier ones
+ are first
+ - Move the List widget section to an appendix
+
Thu Jan 28 12:14:12 GMT 1999 Tony Gale <gale@gtk.org>
* docs/package_tutorial.sh: script to convert and
+Fri Jan 29 09:18:41 GMT 1999 Tony Gale <gale@gtk.org>
+
+ * docs/gtk_tut.sgml:
+ - New sections on the Fixed and Frame containers
+ - Rearrange the Containers section so the easier ones
+ are first
+ - Move the List widget section to an appendix
+
Thu Jan 28 12:14:12 GMT 1999 Tony Gale <gale@gtk.org>
* docs/package_tutorial.sh: script to convert and
+Fri Jan 29 09:18:41 GMT 1999 Tony Gale <gale@gtk.org>
+
+ * docs/gtk_tut.sgml:
+ - New sections on the Fixed and Frame containers
+ - Rearrange the Containers section so the easier ones
+ are first
+ - Move the List widget section to an appendix
+
Thu Jan 28 12:14:12 GMT 1999 Tony Gale <gale@gtk.org>
* docs/package_tutorial.sh: script to convert and
+Fri Jan 29 09:18:41 GMT 1999 Tony Gale <gale@gtk.org>
+
+ * docs/gtk_tut.sgml:
+ - New sections on the Fixed and Frame containers
+ - Rearrange the Containers section so the easier ones
+ are first
+ - Move the List widget section to an appendix
+
Thu Jan 28 12:14:12 GMT 1999 Tony Gale <gale@gtk.org>
* docs/package_tutorial.sh: script to convert and
+Fri Jan 29 09:18:41 GMT 1999 Tony Gale <gale@gtk.org>
+
+ * docs/gtk_tut.sgml:
+ - New sections on the Fixed and Frame containers
+ - Rearrange the Containers section so the easier ones
+ are first
+ - Move the List widget section to an appendix
+
Thu Jan 28 12:14:12 GMT 1999 Tony Gale <gale@gtk.org>
* docs/package_tutorial.sh: script to convert and
+Fri Jan 29 09:18:41 GMT 1999 Tony Gale <gale@gtk.org>
+
+ * docs/gtk_tut.sgml:
+ - New sections on the Fixed and Frame containers
+ - Rearrange the Containers section so the easier ones
+ are first
+ - Move the List widget section to an appendix
+
Thu Jan 28 12:14:12 GMT 1999 Tony Gale <gale@gtk.org>
* docs/package_tutorial.sh: script to convert and
+Fri Jan 29 09:18:41 GMT 1999 Tony Gale <gale@gtk.org>
+
+ * docs/gtk_tut.sgml:
+ - New sections on the Fixed and Frame containers
+ - Rearrange the Containers section so the easier ones
+ are first
+ - Move the List widget section to an appendix
+
Thu Jan 28 12:14:12 GMT 1999 Tony Gale <gale@gtk.org>
* docs/package_tutorial.sh: script to convert and
name="<gale@gtk.org>"></tt>
Ian Main <tt><htmlurl url="mailto:imain@gtk.org"
name="<imain@gtk.org>"></tt>,
-<date>January 27th, 1999
+<date>January 28th, 1999
<!-- ***************************************************************** -->
<sect>Introduction
<sect> Container Widgets
<!-- ***************************************************************** -->
-<!-- ----------------------------------------------------------------- -->
-<sect1> Notebooks
-<p>
-The NoteBook Widget is a collection of 'pages' that overlap each
-other, each page contains different information. This widget has
-become more common lately in GUI programming, and it is a good way to
-show blocks of similar information that warrant separation in their
-display.
+<!-- ----------------------------------------------------------------- -->
+<sect1>The EventBox <label id="sec_EventBox">
+<p>
+Some GTK widgets don't have associated X windows, so they just draw on
+their parents. Because of this, they cannot receive events and if they
+are incorrectly sized, they don't clip so you can get messy
+overwriting etc. If you require more from these widgets, the EventBox
+is for you.
-The first function call you will need to know, as you can probably
-guess by now, is used to create a new notebook widget.
+At first glance, the EventBox widget might appear to be totally
+useless. It draws nothing on the screen and responds to no
+events. However, it does serve a function - it provides an X window
+for its child widget. This is important as many GTK widgets do not
+have an associated X window. Not having an X window saves memory and
+improves performance, but also has some drawbacks. A widget without an
+X window cannot receive events, and does not perform any clipping on
+its contents. Although the name <em/EventBox/ emphasizes the
+event-handling function, the widget can also be used for clipping.
+(and more, see the example below).
+
+To create a new EventBox widget, use:
<tscreen><verb>
-GtkWidget *gtk_notebook_new( void );
+GtkWidget *gtk_event_box_new( void );
</verb></tscreen>
-Once the notebook has been created, there are a number of functions
-that operate on the notebook widget. Let's look at them individually.
-
-The first one we will look at is how to position the page indicators.
-These page indicators or 'tabs' as they are referred to, can be
-positioned in four ways: top, bottom, left, or right.
+A child widget can then be added to this EventBox:
<tscreen><verb>
-void gtk_notebook_set_tab_pos( GtkNotebook *notebook,
- GtkPositionType pos );
+gtk_container_add( GTK_CONTAINER(event_box), widget );
</verb></tscreen>
-GtkPostionType will be one of the following, and they are pretty self explanatory:
-<itemize>
-<item> GTK_POS_LEFT
-<item> GTK_POS_RIGHT
-<item> GTK_POS_TOP
-<item> GTK_POS_BOTTOM
-</itemize>
-
-GTK_POS_TOP is the default.
-
-Next we will look at how to add pages to the notebook. There are three
-ways to add pages to the NoteBook. Let's look at the first two
-together as they are quite similar.
+The following example demonstrates both uses of an EventBox - a label
+is created that is clipped to a small box, and set up so that a
+mouse-click on the label causes the program to exit. Resizing the
+window reveals varying amounts of the label.
<tscreen><verb>
-void gtk_notebook_append_page( GtkNotebook *notebook,
- GtkWidget *child,
- GtkWidget *tab_label );
+/* example-start eventbox eventbox.c */
-void gtk_notebook_prepend_page( GtkNotebook *notebook,
- GtkWidget *child,
- GtkWidget *tab_label );
+#include <gtk/gtk.h>
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *window;
+ GtkWidget *event_box;
+ GtkWidget *label;
+
+ gtk_init (&argc, &argv);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_window_set_title (GTK_WINDOW (window), "Event Box");
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ GTK_SIGNAL_FUNC (gtk_exit), NULL);
+
+ gtk_container_set_border_width (GTK_CONTAINER (window), 10);
+
+ /* Create an EventBox and add it to our toplevel window */
+
+ event_box = gtk_event_box_new ();
+ gtk_container_add (GTK_CONTAINER(window), event_box);
+ gtk_widget_show (event_box);
+
+ /* Create a long label */
+
+ label = gtk_label_new ("Click here to quit, quit, quit, quit, quit");
+ gtk_container_add (GTK_CONTAINER (event_box), label);
+ gtk_widget_show (label);
+
+ /* Clip it short. */
+ gtk_widget_set_usize (label, 110, 20);
+
+ /* And bind an action to it */
+ gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK);
+ gtk_signal_connect (GTK_OBJECT(event_box), "button_press_event",
+ GTK_SIGNAL_FUNC (gtk_exit), NULL);
+
+ /* Yet one more thing you need an X window for ... */
+
+ gtk_widget_realize (event_box);
+ gdk_window_set_cursor (event_box->window, gdk_cursor_new (GDK_HAND1));
+
+ gtk_widget_show (window);
+
+ gtk_main ();
+
+ return(0);
+}
+/* example-end */
</verb></tscreen>
-These functions add pages to the notebook by inserting them from the
-back of the notebook (append), or the front of the notebook (prepend).
-<tt/child/ is the widget that is placed within the notebook page, and
-<tt/tab_label/ is the label for the page being added. The <tt/child/
-widget must be created separately, and is typically a set of options
-setout witin one of the other container widgets, such as a table.
+<!-- ----------------------------------------------------------------- -->
+<sect1> Fixed Container
+<p>
+The Fixed container allows you to place widgets at a fixed position
+within it's window, relative to it's upper left hand corner. The
+position of the widgets can be changed dynamically.
-The final function for adding a page to the notebook contains all of
-the properties of the previous two, but it allows you to specify what
-position you want the page to be in the notebook.
+There are only three functions associated with the fixed widget:
<tscreen><verb>
-void gtk_notebook_insert_page( GtkNotebook *notebook,
- GtkWidget *child,
- GtkWidget *tab_label,
- gint position );
+GtkWidget* gtk_fixed_new( void );
+
+void gtk_fixed_put( GtkFixed *fixed,
+ GtkWidget *widget,
+ gint16 x,
+ gint16 y );
+
+void gtk_fixed_move( GtkFixed *fixed,
+ GtkWidget *widget,
+ gint16 x,
+ gint16 y );
</verb></tscreen>
-The parameters are the same as _append_ and _prepend_ except it
-contains an extra parameter, <tt/position/. This parameter is used to
-specify what place this page will be inserted into.
+The function <tt/gtk_fixed_new/ allows you to create a new Fixed
+container.
-Now that we know how to add a page, lets see how we can remove a page
-from the notebook.
+<tt/gtk_fixed_put/ places <tt/widget/ in the container <tt/fixed/ at
+the position specified by <tt/x/ and <tt/y/.
+
+<tt/gtk_fixed_move/ allows the specified widget to be moved to a new
+position.
+
+The following example illustrates how to use the Fixed Container.
<tscreen><verb>
-void gtk_notebook_remove_page( GtkNotebook *notebook,
- gint page_num );
-</verb></tscreen>
+/* example-start fixed fixed.c */
-This function takes the page specified by <tt/page_num/ and removes it
-from the widget pointed to by <tt/notebook/.
+#include <gtk/gtk.h>
-To find out what the current page is in a notebook use the function:
+/* I'm going to be lazy and use some global variables to
+ * store the position of the widget within the fixed
+ * container */
+gint x=50;
+gint y=50;
-<tscreen><verb>
-gint gtk_notebook_get_current_page( GtkNotebook *notebook );
-</verb></tscreen>
+/* This callback function moves the button to a new position
+ * in the Fixed container. */
+void move_button( GtkWidget *widget,
+ GtkWidget *fixed )
+{
+ x = (x+30)%300;
+ y = (y+50)%300;
+ gtk_fixed_move( GTK_FIXED(fixed), widget, x, y);
+}
-These next two functions are simple calls to move the notebook page
-forward or backward. Simply provide the respective function call with
-the notebook widget you wish to operate on. Note: when the NoteBook is
-currently on the last page, and gtk_notebook_next_page is called, the
-notebook will wrap back to the first page. Likewise, if the NoteBook
-is on the first page, and gtk_notebook_prev_page is called, the
-notebook will wrap to the last page.
+int main( int argc,
+ char *argv[] )
+{
+ /* GtkWidget is the storage type for widgets */
+ GtkWidget *window;
+ GtkWidget *fixed;
+ GtkWidget *button;
+ gint i;
-<tscreen><verb>
-void gtk_notebook_next_page( GtkNoteBook *notebook );
+ /* Initialise GTK */
+ gtk_init(&argc, &argv);
+
+ /* Create a new window */
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(window), "Fixed Container");
-void gtk_notebook_prev_page( GtkNoteBook *notebook );
+ /* Here we connect the "destroy" event to a signal handler */
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
+
+ /* Sets the border width of the window. */
+ gtk_container_set_border_width (GTK_CONTAINER (window), 10);
+
+ /* Create a Fixed Container */
+ fixed = gtk_fixed_new();
+ gtk_container_add(GTK_CONTAINER(window), fixed);
+ gtk_widget_show(fixed);
+
+ for (i = 1 ; i <= 3 ; i++) {
+ /* Creates a new button with the label "Press me" */
+ button = gtk_button_new_with_label ("Press me");
+
+ /* When the button receives the "clicked" signal, it will call the
+ * function move_button() passing it the Fixed Containter as its
+ * argument. */
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (move_button), fixed);
+
+ /* This packs the button into the fixed containers window. */
+ gtk_fixed_put (GTK_FIXED (fixed), button, i*50, i*50);
+
+ /* The final step is to display this newly created widget. */
+ gtk_widget_show (button);
+ }
+
+ /* Display the window */
+ gtk_widget_show (window);
+
+ /* Enter the event loop */
+ gtk_main ();
+
+ return(0);
+}
+/* example-end */
</verb></tscreen>
-This next function sets the 'active' page. If you wish the notebook to
-be opened to page 5 for example, you would use this function. Without
-using this function, the notebook defaults to the first page.
+<!-- ----------------------------------------------------------------- -->
+<sect1> Frames
+<p>
+Frames can be used to enclose one or a group of widgets with a box
+which can optionally be labelled. The position of the label and the
+style of the box can be altered to suit.
+
+A Frame can be created with the following function:
<tscreen><verb>
-void gtk_notebook_set_page( GtkNotebook *notebook,
- gint page_num );
+GtkWidget *gtk_frame_new( const gchar *label );
</verb></tscreen>
-The next two functions add or remove the notebook page tabs and the
-notebook border respectively.
+The label is by default placed in the upper left hand corner of the
+frame. A value of NULL for the <tt/label/ argument will result in no
+label being displayed. The text of the label can be changed using the
+next function.
<tscreen><verb>
-void gtk_notebook_set_show_tabs( GtkNotebook *notebook,
- gboolean show_tabs);
+void gtk_frame_set_label( GtkFrame *frame,
+ const gchar *label );
+</verb></tscreen>
-void gtk_notebook_set_show_border( GtkNotebook *notebook,
- gboolean show_border );
+The position of the label can be changed using this function:
+
+<tscreen><verb>
+void gtk_frame_set_label_align( GtkFrame *frame,
+ gfloat xalign,
+ gfloat yalign );
</verb></tscreen>
-The next function is useful when the you have a large number of pages,
-and the tabs don't fit on the page. It allows the tabs to be scrolled
-through using two arrow buttons.
+<tt/xalign/ and <tt/yalign/ take values between 0.0 and 1.0. <tt/xalign/
+indicates the position of the label along the top horizontal of the
+frame. <tt/yalign/ is not currently used. The default value of xalign
+is 0.0 which places the label at the left hand end of the frame.
+
+The next function alters the style of the box that is used to outline
+the frame.
<tscreen><verb>
-void gtk_notebook_set_scrollable( GtkNotebook *notebook,
- gboolean scrollable );
+void gtk_frame_set_shadow_type( GtkFrame *frame,
+ GtkShadowType type);
</verb></tscreen>
-<tt/show_tabs/, <tt/show_border/ and <tt/scrollable/ can be either
-TRUE or FALSE.
+The <tt/type/ argument can take one of the following values:
+<itemize>
+<item> GTK_SHADOW_NONE
+<item> GTK_SHADOW_IN
+<item> GTK_SHADOW_OUT
+<item> GTK_SHADOW_ETCHED_IN (the default)
+<item> GTK_SHADOW_ETCHED_OUT
+</itemize>
-Now lets look at an example, it is expanded from the testgtk.c code
-that comes with the GTK distribution. This small program creates a
-window with a notebook and six buttons. The notebook contains 11
-pages, added in three different ways, appended, inserted, and
-prepended. The buttons allow you rotate the tab positions, add/remove
-the tabs and border, remove a page, change pages in both a forward and
-backward manner, and exit the program.
+The following code example illustrates the use of the Frame widget.
<tscreen><verb>
-/* example-start notebook notebook.c */
+/* example-start frame frame.c */
#include <gtk/gtk.h>
-/* This function rotates the position of the tabs */
-void rotate_book (GtkButton *button, GtkNotebook *notebook)
+int main( int argc,
+ char *argv[] )
{
- gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4);
-}
+ /* GtkWidget is the storage type for widgets */
+ GtkWidget *window;
+ GtkWidget *frame;
+ GtkWidget *button;
+ gint i;
-/* Add/Remove the page tabs and the borders */
-void tabsborder_book (GtkButton *button, GtkNotebook *notebook)
-{
- gint tval = FALSE;
- gint bval = FALSE;
- if (notebook->show_tabs == 0)
- tval = TRUE;
- if (notebook->show_border == 0)
- bval = TRUE;
+ /* Initialise GTK */
+ gtk_init(&argc, &argv);
- gtk_notebook_set_show_tabs (notebook, tval);
- gtk_notebook_set_show_border (notebook, bval);
-}
+ /* Create a new window */
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(window), "Frame Example");
-/* Remove a page from the notebook */
-void remove_book (GtkButton *button, GtkNotebook *notebook)
-{
- gint page;
-
- page = gtk_notebook_get_current_page(notebook);
- gtk_notebook_remove_page (notebook, page);
- /* Need to refresh the widget --
- This forces the widget to redraw itself. */
- gtk_widget_draw(GTK_WIDGET(notebook), NULL);
-}
+ /* Here we connect the "destroy" event to a signal handler */
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
-void delete (GtkWidget *widget, GtkWidget *event, gpointer data)
-{
- gtk_main_quit ();
-}
+ gtk_widget_set_usize(window, 300, 300);
+ /* Sets the border width of the window. */
+ gtk_container_set_border_width (GTK_CONTAINER (window), 10);
-int main (int argc, char *argv[])
-{
- GtkWidget *window;
- GtkWidget *button;
- GtkWidget *table;
- GtkWidget *notebook;
- GtkWidget *frame;
- GtkWidget *label;
- GtkWidget *checkbutton;
- int i;
- char bufferf[32];
- char bufferl[32];
-
- gtk_init (&argc, &argv);
-
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-
- gtk_signal_connect (GTK_OBJECT (window), "delete_event",
- GTK_SIGNAL_FUNC (delete), NULL);
-
- gtk_container_set_border_width (GTK_CONTAINER (window), 10);
+ /* Create a Frame */
+ frame = gtk_frame_new(NULL);
+ gtk_container_add(GTK_CONTAINER(window), frame);
- table = gtk_table_new(3,6,FALSE);
- gtk_container_add (GTK_CONTAINER (window), table);
-
- /* Create a new notebook, place the position of the tabs */
- notebook = gtk_notebook_new ();
- gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
- gtk_table_attach_defaults(GTK_TABLE(table), notebook, 0,6,0,1);
- gtk_widget_show(notebook);
-
- /* Lets append a bunch of pages to the notebook */
- for (i=0; i < 5; i++) {
- sprintf(bufferf, "Append Frame %d", i+1);
- sprintf(bufferl, "Page %d", i+1);
-
- frame = gtk_frame_new (bufferf);
- gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
- gtk_widget_set_usize (frame, 100, 75);
- gtk_widget_show (frame);
-
- label = gtk_label_new (bufferf);
- gtk_container_add (GTK_CONTAINER (frame), label);
- gtk_widget_show (label);
-
- label = gtk_label_new (bufferl);
- gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
- }
-
- /* Now lets add a page to a specific spot */
- checkbutton = gtk_check_button_new_with_label ("Check me please!");
- gtk_widget_set_usize(checkbutton, 100, 75);
- gtk_widget_show (checkbutton);
-
- label = gtk_label_new ("Add page");
- gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);
-
- /* Now finally lets prepend pages to the notebook */
- for (i=0; i < 5; i++) {
- sprintf(bufferf, "Prepend Frame %d", i+1);
- sprintf(bufferl, "PPage %d", i+1);
-
- frame = gtk_frame_new (bufferf);
- gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
- gtk_widget_set_usize (frame, 100, 75);
- gtk_widget_show (frame);
-
- label = gtk_label_new (bufferf);
- gtk_container_add (GTK_CONTAINER (frame), label);
- gtk_widget_show (label);
-
- label = gtk_label_new (bufferl);
- gtk_notebook_prepend_page (GTK_NOTEBOOK(notebook), frame, label);
- }
-
- /* Set what page to start at (page 4) */
- gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3);
+ /* Set the frames label */
+ gtk_frame_set_label( GTK_FRAME(frame), "GTK Frame Widget" );
- /* Create a bunch of buttons */
- button = gtk_button_new_with_label ("close");
- gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
- GTK_SIGNAL_FUNC (delete), NULL);
- gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,1,2);
- gtk_widget_show(button);
-
- button = gtk_button_new_with_label ("next page");
- gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
- (GtkSignalFunc) gtk_notebook_next_page,
- GTK_OBJECT (notebook));
- gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,1,2);
- gtk_widget_show(button);
-
- button = gtk_button_new_with_label ("prev page");
- gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
- (GtkSignalFunc) gtk_notebook_prev_page,
- GTK_OBJECT (notebook));
- gtk_table_attach_defaults(GTK_TABLE(table), button, 2,3,1,2);
- gtk_widget_show(button);
-
- button = gtk_button_new_with_label ("tab position");
- gtk_signal_connect (GTK_OBJECT (button), "clicked",
- (GtkSignalFunc) rotate_book, GTK_OBJECT(notebook));
- gtk_table_attach_defaults(GTK_TABLE(table), button, 3,4,1,2);
- gtk_widget_show(button);
-
- button = gtk_button_new_with_label ("tabs/border on/off");
- gtk_signal_connect (GTK_OBJECT (button), "clicked",
- (GtkSignalFunc) tabsborder_book,
- GTK_OBJECT (notebook));
- gtk_table_attach_defaults(GTK_TABLE(table), button, 4,5,1,2);
- gtk_widget_show(button);
-
- button = gtk_button_new_with_label ("remove page");
- gtk_signal_connect (GTK_OBJECT (button), "clicked",
- (GtkSignalFunc) remove_book,
- GTK_OBJECT(notebook));
- gtk_table_attach_defaults(GTK_TABLE(table), button, 5,6,1,2);
- gtk_widget_show(button);
-
- gtk_widget_show(table);
- gtk_widget_show(window);
+ /* Align the label at the right of the frame */
+ gtk_frame_set_label_align( GTK_FRAME(frame), 1.0, 0.0);
+
+ /* Set the style of the frame */
+ gtk_frame_set_shadow_type( GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
+
+ gtk_widget_show(frame);
+
+ /* Display the window */
+ gtk_widget_show (window);
- gtk_main ();
+ /* Enter the event loop */
+ gtk_main ();
- return(0);
+ return(0);
}
/* example-end */
-</verb></tscreen>
-
-Hopefully this helps you on your way with creating notebooks for your
-GTK applications.
-
-<!-- ----------------------------------------------------------------- -->
-<sect1>Scrolled Windows
-<p>
-Scrolled windows are used to create a scrollable area inside a real
-window. You may insert any type of widget into a scrolled window, and
-it will be accessible regardless of the size by using the scrollbars.
-The following function is used to create a new scrolled window.
-
-<tscreen><verb>
-GtkWidget *gtk_scrolled_window_new( GtkAdjustment *hadjustment,
- GtkAdjustment *vadjustment );
</verb></tscreen>
-Where the first argument is the adjustment for the horizontal
-direction, and the second, the adjustment for the vertical direction.
-These are almost always set to NULL.
-
+<!-- ----------------------------------------------------------------- -->
+<sect1> Aspect Frames
+<p>
+The aspect frame widget is like a frame widget, except that it also
+enforces the aspect ratio (that is, the ratio of the width to the
+height) of the child widget to have a certain value, adding extra
+space if necessary. This is useful, for instance, if you want to
+preview a larger image. The size of the preview should vary when the
+user resizes the window, but the aspect ratio needs to always match
+the original image.
+
+To create a new aspect frame use:
+
<tscreen><verb>
-void gtk_scrolled_window_set_policy( GtkScrolledWindow *scrolled_window,
- GtkPolicyType hscrollbar_policy,
- GtkPolicyType vscrollbar_policy );
+GtkWidget *gtk_aspect_frame_new( const gchar *label,
+ gfloat xalign,
+ gfloat yalign,
+ gfloat ratio,
+ gint obey_child);
</verb></tscreen>
-
-This sets the policy to be used with respect to the scrollbars.
-The first argument is the scrolled window you wish to change. The second
-sets the policy for the horizontal scrollbar, and the third the policy for
-the vertical scrollbar.
-
-The policy may be one of GTK_POLICY_AUTOMATIC, or GTK_POLICY_ALWAYS.
-GTK_POLICY_AUTOMATIC will automatically decide whether you need
-scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
-there.
-
-You can then place your object into the scrolled window using the
-following function.
-
+
+<tt/xalign/ and <tt/yalign/ specify alignment as with Alignment
+widgets. If <tt/obey_child/ is true, the aspect ratio of a child
+widget will match the aspect ratio of the ideal size it requests.
+Otherwise, it is given by <tt/ratio/.
+
+To change the options of an existing aspect frame, you can use:
+
<tscreen><verb>
-void gtk_scrolled_window_add_with_viewport( GtkScrolledWindow *scrolled_window,
- GtkWidget *child);
+void gtk_aspect_frame_set( GtkAspectFrame *aspect_frame,
+ gfloat xalign,
+ gfloat yalign,
+ gfloat ratio,
+ gint obey_child);
</verb></tscreen>
-
-Here is a simple example that packs 100 toggle buttons into a scrolled
-window. I've only commented on the parts that may be new to you.
-
+
+As an example, the following program uses an AspectFrame to present a
+drawing area whose aspect ratio will always be 2:1, no matter how the
+user resizes the top-level window.
+
<tscreen><verb>
-/* example-start scrolledwin scrolledwin.c */
+/* example-start aspectframe aspectframe.c */
#include <gtk/gtk.h>
-
-void destroy(GtkWidget *widget, gpointer data)
-{
- gtk_main_quit();
-}
-
-int main (int argc, char *argv[])
+
+int
+main (int argc, char *argv[])
{
- static GtkWidget *window;
- GtkWidget *scrolled_window;
- GtkWidget *table;
- GtkWidget *button;
- char buffer[32];
- int i, j;
-
+ GtkWidget *window;
+ GtkWidget *aspect_frame;
+ GtkWidget *drawing_area;
gtk_init (&argc, &argv);
-
- /* Create a new dialog window for the scrolled window to be
- * packed into. A dialog is just like a normal window except it has a
- * vbox and a horizontal separator packed into it. It's just a shortcut
- * for creating dialogs */
- window = gtk_dialog_new ();
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
gtk_signal_connect (GTK_OBJECT (window), "destroy",
- (GtkSignalFunc) destroy, NULL);
- gtk_window_set_title (GTK_WINDOW (window), "GtkScrolledWindow example");
- gtk_container_set_border_width (GTK_CONTAINER (window), 0);
- gtk_widget_set_usize(window, 300, 300);
-
- /* create a new scrolled window. */
- scrolled_window = gtk_scrolled_window_new (NULL, NULL);
-
- gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
-
- /* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS.
- * GTK_POLICY_AUTOMATIC will automatically decide whether you need
- * scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
- * there. The first one is the horizontal scrollbar, the second,
- * the vertical. */
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
- /* The dialog window is created with a vbox packed into it. */
- gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window,
- TRUE, TRUE, 0);
- gtk_widget_show (scrolled_window);
-
- /* create a table of 10 by 10 squares. */
- table = gtk_table_new (10, 10, FALSE);
-
- /* set the spacing to 10 on x and 10 on y */
- gtk_table_set_row_spacings (GTK_TABLE (table), 10);
- gtk_table_set_col_spacings (GTK_TABLE (table), 10);
-
- /* pack the table into the scrolled window */
- gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window),
- table);
- gtk_widget_show (table);
-
- /* this simply creates a grid of toggle buttons on the table
- * to demonstrate the scrolled window. */
- for (i = 0; i < 10; i++)
- for (j = 0; j < 10; j++) {
- sprintf (buffer, "button (%d,%d)\n", i, j);
- button = gtk_toggle_button_new_with_label (buffer);
- gtk_table_attach_defaults (GTK_TABLE (table), button,
- i, i+1, j, j+1);
- gtk_widget_show (button);
- }
-
- /* Add a "close" button to the bottom of the dialog */
- button = gtk_button_new_with_label ("close");
- gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
- (GtkSignalFunc) gtk_widget_destroy,
- GTK_OBJECT (window));
-
- /* this makes it so the button is the default. */
-
- GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
- gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0);
-
- /* This grabs this button to be the default button. Simply hitting
- * the "Enter" key will cause this button to activate. */
- gtk_widget_grab_default (button);
- gtk_widget_show (button);
-
+ GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
+ gtk_container_set_border_width (GTK_CONTAINER (window), 10);
+
+ /* Create an aspect_frame and add it to our toplevel window */
+
+ aspect_frame = gtk_aspect_frame_new ("2x1", /* label */
+ 0.5, /* center x */
+ 0.5, /* center y */
+ 2, /* xsize/ysize = 2 */
+ FALSE /* ignore child's aspect */);
+
+ gtk_container_add (GTK_CONTAINER(window), aspect_frame);
+ gtk_widget_show (aspect_frame);
+
+ /* Now add a child widget to the aspect frame */
+
+ drawing_area = gtk_drawing_area_new ();
+
+ /* Ask for a 200x200 window, but the AspectFrame will give us a 200x100
+ * window since we are forcing a 2x1 aspect ratio */
+ gtk_widget_set_usize (drawing_area, 200, 200);
+ gtk_container_add (GTK_CONTAINER(aspect_frame), drawing_area);
+ gtk_widget_show (drawing_area);
+
gtk_widget_show (window);
-
- gtk_main();
-
- return(0);
+ gtk_main ();
+ return 0;
}
/* example-end */
</verb></tscreen>
-Try playing with resizing the window. You'll notice how the scrollbars
-react. You may also wish to use the gtk_widget_set_usize() call to set
-the default size of the window or other widgets.
-
<!-- ----------------------------------------------------------------- -->
<sect1> Paned Window Widgets
<p>
/* example-end */
</verb></tscreen>
+<!-- ----------------------------------------------------------------- -->
+<sect1>Scrolled Windows
+<p>
+Scrolled windows are used to create a scrollable area inside a real
+window. You may insert any type of widget into a scrolled window, and
+it will be accessible regardless of the size by using the scrollbars.
+
+The following function is used to create a new scrolled window.
+
+<tscreen><verb>
+GtkWidget *gtk_scrolled_window_new( GtkAdjustment *hadjustment,
+ GtkAdjustment *vadjustment );
+</verb></tscreen>
+
+Where the first argument is the adjustment for the horizontal
+direction, and the second, the adjustment for the vertical direction.
+These are almost always set to NULL.
+
+<tscreen><verb>
+void gtk_scrolled_window_set_policy( GtkScrolledWindow *scrolled_window,
+ GtkPolicyType hscrollbar_policy,
+ GtkPolicyType vscrollbar_policy );
+</verb></tscreen>
+
+This sets the policy to be used with respect to the scrollbars.
+The first argument is the scrolled window you wish to change. The second
+sets the policy for the horizontal scrollbar, and the third the policy for
+the vertical scrollbar.
+
+The policy may be one of GTK_POLICY_AUTOMATIC, or GTK_POLICY_ALWAYS.
+GTK_POLICY_AUTOMATIC will automatically decide whether you need
+scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
+there.
+
+You can then place your object into the scrolled window using the
+following function.
+
+<tscreen><verb>
+void gtk_scrolled_window_add_with_viewport( GtkScrolledWindow *scrolled_window,
+ GtkWidget *child);
+</verb></tscreen>
+
+Here is a simple example that packs 100 toggle buttons into a scrolled
+window. I've only commented on the parts that may be new to you.
+
+<tscreen><verb>
+/* example-start scrolledwin scrolledwin.c */
+
+#include <gtk/gtk.h>
+
+void destroy(GtkWidget *widget, gpointer data)
+{
+ gtk_main_quit();
+}
+
+int main (int argc, char *argv[])
+{
+ static GtkWidget *window;
+ GtkWidget *scrolled_window;
+ GtkWidget *table;
+ GtkWidget *button;
+ char buffer[32];
+ int i, j;
+
+ gtk_init (&argc, &argv);
+
+ /* Create a new dialog window for the scrolled window to be
+ * packed into. A dialog is just like a normal window except it has a
+ * vbox and a horizontal separator packed into it. It's just a shortcut
+ * for creating dialogs */
+ window = gtk_dialog_new ();
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy, NULL);
+ gtk_window_set_title (GTK_WINDOW (window), "GtkScrolledWindow example");
+ gtk_container_set_border_width (GTK_CONTAINER (window), 0);
+ gtk_widget_set_usize(window, 300, 300);
+
+ /* create a new scrolled window. */
+ scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+
+ gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
+
+ /* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS.
+ * GTK_POLICY_AUTOMATIC will automatically decide whether you need
+ * scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
+ * there. The first one is the horizontal scrollbar, the second,
+ * the vertical. */
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+ /* The dialog window is created with a vbox packed into it. */
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window,
+ TRUE, TRUE, 0);
+ gtk_widget_show (scrolled_window);
+
+ /* create a table of 10 by 10 squares. */
+ table = gtk_table_new (10, 10, FALSE);
+
+ /* set the spacing to 10 on x and 10 on y */
+ gtk_table_set_row_spacings (GTK_TABLE (table), 10);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 10);
+
+ /* pack the table into the scrolled window */
+ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window),
+ table);
+ gtk_widget_show (table);
+
+ /* this simply creates a grid of toggle buttons on the table
+ * to demonstrate the scrolled window. */
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++) {
+ sprintf (buffer, "button (%d,%d)\n", i, j);
+ button = gtk_toggle_button_new_with_label (buffer);
+ gtk_table_attach_defaults (GTK_TABLE (table), button,
+ i, i+1, j, j+1);
+ gtk_widget_show (button);
+ }
+
+ /* Add a "close" button to the bottom of the dialog */
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+
+ /* this makes it so the button is the default. */
+
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0);
+
+ /* This grabs this button to be the default button. Simply hitting
+ * the "Enter" key will cause this button to activate. */
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+
+ gtk_widget_show (window);
+
+ gtk_main();
+
+ return(0);
+}
+/* example-end */
+</verb></tscreen>
+
+Try playing with resizing the window. You'll notice how the scrollbars
+react. You may also wish to use the gtk_widget_set_usize() call to set
+the default size of the window or other widgets.
+
<!-- ----------------------------------------------------------------- -->
<sect1>Toolbar
<p>
".............++++..............."};
</verb></tscreen>
-<!-- ----------------------------------------------------------------- -->
-<sect1> Aspect Frames
+<!-- ----------------------------------------------------------------- -->
+<sect1> Notebooks
<p>
-The aspect frame widget is like a frame widget, except that it also
-enforces the aspect ratio (that is, the ratio of the width to the
-height) of the child widget to have a certain value, adding extra
-space if necessary. This is useful, for instance, if you want to
-preview a larger image. The size of the preview should vary when the
-user resizes the window, but the aspect ratio needs to always match
-the original image.
-
-To create a new aspect frame use:
-
-<tscreen><verb>
-GtkWidget *gtk_aspect_frame_new( const gchar *label,
- gfloat xalign,
- gfloat yalign,
- gfloat ratio,
- gint obey_child);
-</verb></tscreen>
-
-<tt/xalign/ and <tt/yalign/ specify alignment as with Alignment
-widgets. If <tt/obey_child/ is true, the aspect ratio of a child
-widget will match the aspect ratio of the ideal size it requests.
-Otherwise, it is given by <tt/ratio/.
-
-To change the options of an existing aspect frame, you can use:
-
+The NoteBook Widget is a collection of 'pages' that overlap each
+other, each page contains different information. This widget has
+become more common lately in GUI programming, and it is a good way to
+show blocks of similar information that warrant separation in their
+display.
+
+The first function call you will need to know, as you can probably
+guess by now, is used to create a new notebook widget.
+
<tscreen><verb>
-void gtk_aspect_frame_set( GtkAspectFrame *aspect_frame,
- gfloat xalign,
- gfloat yalign,
- gfloat ratio,
- gint obey_child);
+GtkWidget *gtk_notebook_new( void );
</verb></tscreen>
-
-As an example, the following program uses an AspectFrame to present a
-drawing area whose aspect ratio will always be 2:1, no matter how the
-user resizes the top-level window.
-
-<tscreen><verb>
-/* example-start aspectframe aspectframe.c */
-#include <gtk/gtk.h>
-
-int
-main (int argc, char *argv[])
-{
- GtkWidget *window;
- GtkWidget *aspect_frame;
- GtkWidget *drawing_area;
- gtk_init (&argc, &argv);
-
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
- gtk_signal_connect (GTK_OBJECT (window), "destroy",
- GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
- gtk_container_set_border_width (GTK_CONTAINER (window), 10);
-
- /* Create an aspect_frame and add it to our toplevel window */
-
- aspect_frame = gtk_aspect_frame_new ("2x1", /* label */
- 0.5, /* center x */
- 0.5, /* center y */
- 2, /* xsize/ysize = 2 */
- FALSE /* ignore child's aspect */);
-
- gtk_container_add (GTK_CONTAINER(window), aspect_frame);
- gtk_widget_show (aspect_frame);
-
- /* Now add a child widget to the aspect frame */
-
- drawing_area = gtk_drawing_area_new ();
-
- /* Ask for a 200x200 window, but the AspectFrame will give us a 200x100
- * window since we are forcing a 2x1 aspect ratio */
- gtk_widget_set_usize (drawing_area, 200, 200);
- gtk_container_add (GTK_CONTAINER(aspect_frame), drawing_area);
- gtk_widget_show (drawing_area);
-
- gtk_widget_show (window);
- gtk_main ();
- return 0;
-}
-/* example-end */
+Once the notebook has been created, there are a number of functions
+that operate on the notebook widget. Let's look at them individually.
+
+The first one we will look at is how to position the page indicators.
+These page indicators or 'tabs' as they are referred to, can be
+positioned in four ways: top, bottom, left, or right.
+
+<tscreen><verb>
+void gtk_notebook_set_tab_pos( GtkNotebook *notebook,
+ GtkPositionType pos );
</verb></tscreen>
-<!-- ----------------------------------------------------------------- -->
-<sect1>The EventBox <label id="sec_EventBox">
-<p>
-Some gtk widgets don't have associated X windows, so they just draw on
-their parents. Because of this, they cannot receive events and if they
-are incorrectly sized, they don't clip so you can get messy
-overwriting etc. If you require more from these widgets, the EventBox
-is for you.
+GtkPostionType will be one of the following, and they are pretty self explanatory:
+<itemize>
+<item> GTK_POS_LEFT
+<item> GTK_POS_RIGHT
+<item> GTK_POS_TOP
+<item> GTK_POS_BOTTOM
+</itemize>
-At first glance, the EventBox widget might appear to be totally
-useless. It draws nothing on the screen and responds to no
-events. However, it does serve a function - it provides an X window
-for its child widget. This is important as many GTK widgets do not
-have an associated X window. Not having an X window saves memory and
-improves performance, but also has some drawbacks. A widget without an
-X window cannot receive events, and does not perform any clipping on
-its contents. Although the name <em/EventBox/ emphasizes the
-event-handling function, the widget can also be used for clipping.
-(and more, see the example below).
+GTK_POS_TOP is the default.
-To create a new EventBox widget, use:
+Next we will look at how to add pages to the notebook. There are three
+ways to add pages to the NoteBook. Let's look at the first two
+together as they are quite similar.
<tscreen><verb>
-GtkWidget *gtk_event_box_new( void );
+void gtk_notebook_append_page( GtkNotebook *notebook,
+ GtkWidget *child,
+ GtkWidget *tab_label );
+
+void gtk_notebook_prepend_page( GtkNotebook *notebook,
+ GtkWidget *child,
+ GtkWidget *tab_label );
</verb></tscreen>
-A child widget can then be added to this EventBox:
+These functions add pages to the notebook by inserting them from the
+back of the notebook (append), or the front of the notebook (prepend).
+<tt/child/ is the widget that is placed within the notebook page, and
+<tt/tab_label/ is the label for the page being added. The <tt/child/
+widget must be created separately, and is typically a set of options
+setout witin one of the other container widgets, such as a table.
+
+The final function for adding a page to the notebook contains all of
+the properties of the previous two, but it allows you to specify what
+position you want the page to be in the notebook.
<tscreen><verb>
-gtk_container_add( GTK_CONTAINER(event_box), widget );
+void gtk_notebook_insert_page( GtkNotebook *notebook,
+ GtkWidget *child,
+ GtkWidget *tab_label,
+ gint position );
</verb></tscreen>
-The following example demonstrates both uses of an EventBox - a label
-is created that is clipped to a small box, and set up so that a
-mouse-click on the label causes the program to exit. Resizing the
-window reveals varying amounts of the label.
-
-<tscreen><verb>
-/* example-start eventbox eventbox.c */
+The parameters are the same as _append_ and _prepend_ except it
+contains an extra parameter, <tt/position/. This parameter is used to
+specify what place this page will be inserted into.
-#include <gtk/gtk.h>
+Now that we know how to add a page, lets see how we can remove a page
+from the notebook.
-int
-main (int argc, char *argv[])
-{
- GtkWidget *window;
- GtkWidget *event_box;
- GtkWidget *label;
-
- gtk_init (&argc, &argv);
-
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-
- gtk_window_set_title (GTK_WINDOW (window), "Event Box");
-
- gtk_signal_connect (GTK_OBJECT (window), "destroy",
- GTK_SIGNAL_FUNC (gtk_exit), NULL);
-
- gtk_container_set_border_width (GTK_CONTAINER (window), 10);
-
- /* Create an EventBox and add it to our toplevel window */
-
- event_box = gtk_event_box_new ();
- gtk_container_add (GTK_CONTAINER(window), event_box);
- gtk_widget_show (event_box);
-
- /* Create a long label */
-
- label = gtk_label_new ("Click here to quit, quit, quit, quit, quit");
- gtk_container_add (GTK_CONTAINER (event_box), label);
- gtk_widget_show (label);
-
- /* Clip it short. */
- gtk_widget_set_usize (label, 110, 20);
-
- /* And bind an action to it */
- gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK);
- gtk_signal_connect (GTK_OBJECT(event_box), "button_press_event",
- GTK_SIGNAL_FUNC (gtk_exit), NULL);
-
- /* Yet one more thing you need an X window for ... */
-
- gtk_widget_realize (event_box);
- gdk_window_set_cursor (event_box->window, gdk_cursor_new (GDK_HAND1));
-
- gtk_widget_show (window);
-
- gtk_main ();
-
- return(0);
-}
-/* example-end */
+<tscreen><verb>
+void gtk_notebook_remove_page( GtkNotebook *notebook,
+ gint page_num );
</verb></tscreen>
-<!-- ***************************************************************** -->
-<sect>CList Widget
-<!-- ***************************************************************** -->
-
-<!-- ----------------------------------------------------------------- -->
-<p>
-The GtkCList widget has replaced the GtkList widget (which is still
-available).
+This function takes the page specified by <tt/page_num/ and removes it
+from the widget pointed to by <tt/notebook/.
-The GtkCList widget is a multi-column list widget that is capable of
-handling literally thousands of rows of information. Each column can
-optionally have a title, which itself is optionally active, allowing
-us to bind a function to its selection.
+To find out what the current page is in a notebook use the function:
-<!-- ----------------------------------------------------------------- -->
-<sect1>Creating a GtkCList widget
-<p>
-Creating a GtkCList is quite straightforward, once you have learned
-about widgets in general. It provides the almost standard two ways,
-that is the hard way, and the easy way. But before we create it, there
-is one thing we should figure out beforehand: how many columns should
-it have?
+<tscreen><verb>
+gint gtk_notebook_get_current_page( GtkNotebook *notebook );
+</verb></tscreen>
-Not all columns have to be visible and can be used to store data that
-is related to a certain cell in the list.
+These next two functions are simple calls to move the notebook page
+forward or backward. Simply provide the respective function call with
+the notebook widget you wish to operate on. Note: when the NoteBook is
+currently on the last page, and gtk_notebook_next_page is called, the
+notebook will wrap back to the first page. Likewise, if the NoteBook
+is on the first page, and gtk_notebook_prev_page is called, the
+notebook will wrap to the last page.
<tscreen><verb>
-GtkWidget *gtk_clist_new ( gint columns );
+void gtk_notebook_next_page( GtkNoteBook *notebook );
-GtkWidget *gtk_clist_new_with_titles( gint columns,
- gchar *titles[] );
+void gtk_notebook_prev_page( GtkNoteBook *notebook );
</verb></tscreen>
-The first form is very straight forward, the second might require some
-explanation. Each column can have a title associated with it, and this
-title can be a label or a button that reacts when we click on it. If
-we use the second form, we must provide pointers to the title texts,
-and the number of pointers should equal the number of columns
-specified. Of course we can always use the first form, and manually
+This next function sets the 'active' page. If you wish the notebook to
+be opened to page 5 for example, you would use this function. Without
+using this function, the notebook defaults to the first page.
+
+<tscreen><verb>
+void gtk_notebook_set_page( GtkNotebook *notebook,
+ gint page_num );
+</verb></tscreen>
+
+The next two functions add or remove the notebook page tabs and the
+notebook border respectively.
+
+<tscreen><verb>
+void gtk_notebook_set_show_tabs( GtkNotebook *notebook,
+ gboolean show_tabs);
+
+void gtk_notebook_set_show_border( GtkNotebook *notebook,
+ gboolean show_border );
+</verb></tscreen>
+
+The next function is useful when the you have a large number of pages,
+and the tabs don't fit on the page. It allows the tabs to be scrolled
+through using two arrow buttons.
+
+<tscreen><verb>
+void gtk_notebook_set_scrollable( GtkNotebook *notebook,
+ gboolean scrollable );
+</verb></tscreen>
+
+<tt/show_tabs/, <tt/show_border/ and <tt/scrollable/ can be either
+TRUE or FALSE.
+
+Now lets look at an example, it is expanded from the testgtk.c code
+that comes with the GTK distribution. This small program creates a
+window with a notebook and six buttons. The notebook contains 11
+pages, added in three different ways, appended, inserted, and
+prepended. The buttons allow you rotate the tab positions, add/remove
+the tabs and border, remove a page, change pages in both a forward and
+backward manner, and exit the program.
+
+<tscreen><verb>
+/* example-start notebook notebook.c */
+
+#include <gtk/gtk.h>
+
+/* This function rotates the position of the tabs */
+void rotate_book (GtkButton *button, GtkNotebook *notebook)
+{
+ gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4);
+}
+
+/* Add/Remove the page tabs and the borders */
+void tabsborder_book (GtkButton *button, GtkNotebook *notebook)
+{
+ gint tval = FALSE;
+ gint bval = FALSE;
+ if (notebook->show_tabs == 0)
+ tval = TRUE;
+ if (notebook->show_border == 0)
+ bval = TRUE;
+
+ gtk_notebook_set_show_tabs (notebook, tval);
+ gtk_notebook_set_show_border (notebook, bval);
+}
+
+/* Remove a page from the notebook */
+void remove_book (GtkButton *button, GtkNotebook *notebook)
+{
+ gint page;
+
+ page = gtk_notebook_get_current_page(notebook);
+ gtk_notebook_remove_page (notebook, page);
+ /* Need to refresh the widget --
+ This forces the widget to redraw itself. */
+ gtk_widget_draw(GTK_WIDGET(notebook), NULL);
+}
+
+void delete (GtkWidget *widget, GtkWidget *event, gpointer data)
+{
+ gtk_main_quit ();
+}
+
+int main (int argc, char *argv[])
+{
+ GtkWidget *window;
+ GtkWidget *button;
+ GtkWidget *table;
+ GtkWidget *notebook;
+ GtkWidget *frame;
+ GtkWidget *label;
+ GtkWidget *checkbutton;
+ int i;
+ char bufferf[32];
+ char bufferl[32];
+
+ gtk_init (&argc, &argv);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ GTK_SIGNAL_FUNC (delete), NULL);
+
+ gtk_container_set_border_width (GTK_CONTAINER (window), 10);
+
+ table = gtk_table_new(3,6,FALSE);
+ gtk_container_add (GTK_CONTAINER (window), table);
+
+ /* Create a new notebook, place the position of the tabs */
+ notebook = gtk_notebook_new ();
+ gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
+ gtk_table_attach_defaults(GTK_TABLE(table), notebook, 0,6,0,1);
+ gtk_widget_show(notebook);
+
+ /* Lets append a bunch of pages to the notebook */
+ for (i=0; i < 5; i++) {
+ sprintf(bufferf, "Append Frame %d", i+1);
+ sprintf(bufferl, "Page %d", i+1);
+
+ frame = gtk_frame_new (bufferf);
+ gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
+ gtk_widget_set_usize (frame, 100, 75);
+ gtk_widget_show (frame);
+
+ label = gtk_label_new (bufferf);
+ gtk_container_add (GTK_CONTAINER (frame), label);
+ gtk_widget_show (label);
+
+ label = gtk_label_new (bufferl);
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
+ }
+
+ /* Now lets add a page to a specific spot */
+ checkbutton = gtk_check_button_new_with_label ("Check me please!");
+ gtk_widget_set_usize(checkbutton, 100, 75);
+ gtk_widget_show (checkbutton);
+
+ label = gtk_label_new ("Add page");
+ gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);
+
+ /* Now finally lets prepend pages to the notebook */
+ for (i=0; i < 5; i++) {
+ sprintf(bufferf, "Prepend Frame %d", i+1);
+ sprintf(bufferl, "PPage %d", i+1);
+
+ frame = gtk_frame_new (bufferf);
+ gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
+ gtk_widget_set_usize (frame, 100, 75);
+ gtk_widget_show (frame);
+
+ label = gtk_label_new (bufferf);
+ gtk_container_add (GTK_CONTAINER (frame), label);
+ gtk_widget_show (label);
+
+ label = gtk_label_new (bufferl);
+ gtk_notebook_prepend_page (GTK_NOTEBOOK(notebook), frame, label);
+ }
+
+ /* Set what page to start at (page 4) */
+ gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3);
+
+ /* Create a bunch of buttons */
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (delete), NULL);
+ gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,1,2);
+ gtk_widget_show(button);
+
+ button = gtk_button_new_with_label ("next page");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_notebook_next_page,
+ GTK_OBJECT (notebook));
+ gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,1,2);
+ gtk_widget_show(button);
+
+ button = gtk_button_new_with_label ("prev page");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_notebook_prev_page,
+ GTK_OBJECT (notebook));
+ gtk_table_attach_defaults(GTK_TABLE(table), button, 2,3,1,2);
+ gtk_widget_show(button);
+
+ button = gtk_button_new_with_label ("tab position");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) rotate_book, GTK_OBJECT(notebook));
+ gtk_table_attach_defaults(GTK_TABLE(table), button, 3,4,1,2);
+ gtk_widget_show(button);
+
+ button = gtk_button_new_with_label ("tabs/border on/off");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) tabsborder_book,
+ GTK_OBJECT (notebook));
+ gtk_table_attach_defaults(GTK_TABLE(table), button, 4,5,1,2);
+ gtk_widget_show(button);
+
+ button = gtk_button_new_with_label ("remove page");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) remove_book,
+ GTK_OBJECT(notebook));
+ gtk_table_attach_defaults(GTK_TABLE(table), button, 5,6,1,2);
+ gtk_widget_show(button);
+
+ gtk_widget_show(table);
+ gtk_widget_show(window);
+
+ gtk_main ();
+
+ return(0);
+}
+/* example-end */
+</verb></tscreen>
+
+Hopefully this helps you on your way with creating notebooks for your
+GTK applications.
+
+<!-- ***************************************************************** -->
+<sect>CList Widget
+<!-- ***************************************************************** -->
+
+<!-- ----------------------------------------------------------------- -->
+<p>
+The GtkCList widget has replaced the GtkList widget (which is still
+available).
+
+The GtkCList widget is a multi-column list widget that is capable of
+handling literally thousands of rows of information. Each column can
+optionally have a title, which itself is optionally active, allowing
+us to bind a function to its selection.
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>Creating a GtkCList widget
+<p>
+Creating a GtkCList is quite straightforward, once you have learned
+about widgets in general. It provides the almost standard two ways,
+that is the hard way, and the easy way. But before we create it, there
+is one thing we should figure out beforehand: how many columns should
+it have?
+
+Not all columns have to be visible and can be used to store data that
+is related to a certain cell in the list.
+
+<tscreen><verb>
+GtkWidget *gtk_clist_new ( gint columns );
+
+GtkWidget *gtk_clist_new_with_titles( gint columns,
+ gchar *titles[] );
+</verb></tscreen>
+
+The first form is very straight forward, the second might require some
+explanation. Each column can have a title associated with it, and this
+title can be a label or a button that reacts when we click on it. If
+we use the second form, we must provide pointers to the title texts,
+and the number of pointers should equal the number of columns
+specified. Of course we can always use the first form, and manually
add titles later.
Note: the GtkCList widget does not have it's own scrollbars and should
</verb></tscreen>
<!-- ***************************************************************** -->
-<sect> List Widget
+<sect> Tree Widget<label id="sec_Tree_Widgets">
<!-- ***************************************************************** -->
<p>
-NOTE: The GtkList widget has been superseded by the GtkCList widget.
-
-The GtkList widget is designed to act as a vertical container for
-widgets that should be of the type GtkListItem.
+The purpose of tree widgets is to display hierarchically-organized
+data. The GtkTree widget itself is a vertical container for widgets of
+type GtkTreeItem. GtkTree itself is not terribly different from
+GtkList - both are derived directly from GtkContainer, and the
+GtkContainer methods work in the same way on GtkTree widgets as on
+GtkList widgets. The difference is that GtkTree widgets can be nested
+within other GtkTree widgets. We'll see how to do this shortly.
-A GtkList widget has its own window to receive events and its own
-background color which is usually white. As it is directly derived
-from a GtkContainer it can be treated as such by using the
-GTK_CONTAINER(List) macro, see the GtkContainer widget for more on
-this. One should already be familiar with the usage of a GList and
-its related functions g_list_*() to be able to use the GtkList widget
-to it full extent.
+The GtkTree widget has its own window, and defaults to a white
+background, as does GtkList. Also, most of the GtkTree methods work in
+the same way as the corresponding GtkList ones. However, GtkTree is
+not derived from GtkList, so you cannot use them interchangeably.
-There is one field inside the structure definition of the GtkList
-widget that will be of greater interest to us, this is:
+<sect1> Creating a Tree
+<p>
+A GtkTree is created in the usual way, using:
<tscreen><verb>
-struct _GtkList
-{
- ...
- GList *selection;
- guint selection_mode;
- ...
-};
+GtkWidget* gtk_tree_new( void );
</verb></tscreen>
-The selection field of a GtkList points to a linked list of all items
-that are currently selected, or NULL if the selection is empty. So to
-learn about the current selection we read the GTK_LIST()->selection
-field, but do not modify it since the internal fields are maintained
-by the gtk_list_*() functions.
+Like the GtkList widget, a GtkTree will simply keep growing as more
+items are added to it, as well as when subtrees are expanded. For
+this reason, they are almost always packed into a
+GtkScrolledWindow. You might want to use gtk_widget_set_usize() on the
+scrolled window to ensure that it is big enough to see the tree's
+items, as the default size for GtkScrolledWindow is quite small.
-The selection_mode of the GtkList determines the selection facilities
-of a GtkList and therefore the contents of the GTK_LIST()->selection
-field. The selection_mode may be one of the following:
+Now that you have a tree, you'll probably want to add some items to
+it. <ref id="sec_Tree_Item_Widget" name="The Tree Item Widget"> below
+explains the gory details of GtkTreeItem. For now, it'll suffice to
+create one, using:
-<itemize>
-<item> GTK_SELECTION_SINGLE - The selection is either NULL
- or contains a GList pointer
- for a single selected item.
+<tscreen><verb>
+GtkWidget* gtk_tree_item_new_with_label( gchar *label );
+</verb></tscreen>
-<item> GTK_SELECTION_BROWSE - The selection is NULL if the list
- contains no widgets or insensitive
- ones only, otherwise it contains
- a GList pointer for one GList
- structure, and therefore exactly
- one list item.
+You can then add it to the tree using one of the following (see
+<ref id="sec_GtkTree_Functions" name="Functions and Macros">
+below for more options):
-<item> GTK_SELECTION_MULTIPLE - The selection is NULL if no list
- items are selected or a GList pointer
- for the first selected item. That
- in turn points to a GList structure
- for the second selected item and so
- on.
+<tscreen><verb>
+void gtk_tree_append( GtkTree *tree,
+ GtkWidget *tree_item );
-<item> GTK_SELECTION_EXTENDED - The selection is always NULL.
-</itemize>
+void gtk_tree_prepend( GtkTree *tree,
+ GtkWidget *tree_item );
+</verb></tscreen>
-The default is GTK_SELECTION_MULTIPLE.
+Note that you must add items to a GtkTree one at a time - there is no
+equivalent to gtk_list_*_items().
<!-- ----------------------------------------------------------------- -->
-<sect1> Signals
+<sect1> Adding a Subtree
<p>
+A subtree is created like any other GtkTree widget. A subtree is added
+to another tree beneath a tree item, using:
+
<tscreen><verb>
-void selection_changed( GtkList *list );
+void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
+ GtkWidget *subtree );
</verb></tscreen>
-This signal will be invoked whenever the selection field of a GtkList
-has changed. This happens when a child of the GtkList got selected or
-deselected.
+You do not need to call gtk_widget_show() on a subtree before or after
+adding it to a GtkTreeItem. However, you <em>must</em> have added the
+GtkTreeItem in question to a parent tree before calling
+gtk_tree_item_set_subtree(). This is because, technically, the parent
+of the subtree is <em>not</em> the GtkTreeItem which "owns" it, but
+rather the GtkTree which holds that GtkTreeItem.
-<tscreen><verb>
-void select_child( GtkList *list,
- GtkWidget *child);
-</verb></tscreen>
+When you add a subtree to a GtkTreeItem, a plus or minus sign appears
+beside it, which the user can click on to "expand" or "collapse" it,
+meaning, to show or hide its subtree. GtkTreeItems are collapsed by
+default. Note that when you collapse a GtkTreeItem, any selected
+items in its subtree remain selected, which may not be what the user
+expects.
-This signal is invoked when a child of the GtkList is about to get
-selected. This happens mainly on calls to gtk_list_select_item(),
-gtk_list_select_child(), button presses and sometimes indirectly
-triggered on some else occasions where children get added to or
-removed from the GtkList.
+<!-- ----------------------------------------------------------------- -->
+<sect1> Handling the Selection List
+<p>
+As with GtkList, the GtkTree type has a <tt>selection</tt> field, and
+it is possible to control the behaviour of the tree (somewhat) by
+setting the selection type using:
<tscreen><verb>
-void unselect_child( GtkList *list,
- GtkWidget *child );
+void gtk_tree_set_selection_mode( GtkTree *tree,
+ GtkSelectionMode mode );
</verb></tscreen>
-This signal is invoked when a child of the GtkList is about to get
-deselected. This happens mainly on calls to gtk_list_unselect_item(),
-gtk_list_unselect_child(), button presses and sometimes indirectly
-triggered on some else occasions where children get added to or
-removed from the GtkList.
+The semantics associated with the various selection modes are
+described in the section on the GtkList widget. As with the GtkList
+widget, the "select_child", "unselect_child" (not really - see <ref
+id="sec_GtkTree_Signals" name="Signals"> below for an explanation),
+and "selection_changed" signals are emitted when list items are
+selected or unselected. However, in order to take advantage of these
+signals, you need to know <em>which</em> GtkTree widget they will be
+emitted by, and where to find the list of selected items.
-<!-- ----------------------------------------------------------------- -->
-<sect1> Functions
+This is a source of potential confusion. The best way to explain this
+is that though all GtkTree widgets are created equal, some are more
+equal than others. All GtkTree widgets have their own X window, and
+can therefore receive events such as mouse clicks (if their
+GtkTreeItems or their children don't catch them first!). However, to
+make GTK_SELECTION_SINGLE and GTK_SELECTION_BROWSE selection types
+behave in a sane manner, the list of selected items is specific to the
+topmost GtkTree widget in a hierarchy, known as the "root tree".
+
+Thus, accessing the <tt>selection</tt>field directly in an arbitrary
+GtkTree widget is not a good idea unless you <em>know</em> it's the
+root tree. Instead, use the GTK_TREE_SELECTION (Tree) macro, which
+gives the root tree's selection list as a GList pointer. Of course,
+this list can include items that are not in the subtree in question if
+the selection type is GTK_SELECTION_MULTIPLE.
+
+Finally, the "select_child" (and "unselect_child", in theory) signals
+are emitted by all trees, but the "selection_changed" signal is only
+emitted by the root tree. Consequently, if you want to handle the
+"select_child" signal for a tree and all its subtrees, you will have
+to call gtk_signal_connect() for every subtree.
+
+<sect1> Tree Widget Internals
<p>
+The GtkTree's struct definition looks like this:
+
<tscreen><verb>
-guint gtk_list_get_type( void );
+struct _GtkTree
+{
+ GtkContainer container;
+
+ GList *children;
+
+ GtkTree* root_tree; /* owner of selection list */
+ GtkWidget* tree_owner;
+ GList *selection;
+ guint level;
+ guint indent_value;
+ guint current_indent;
+ guint selection_mode : 2;
+ guint view_mode : 1;
+ guint view_line : 1;
+};
</verb></tscreen>
-Returns the `GtkList' type identifier.
+The perils associated with accessing the <tt>selection</tt> field
+directly have already been mentioned. The other important fields of
+the struct can also be accessed with handy macros or class functions.
+GTK_TREE_IS_ROOT_TREE (Tree) returns a boolean value which indicates
+whether a tree is the root tree in a GtkTree hierarchy, while
+GTK_TREE_ROOT_TREE (Tree) returns the root tree, an object of type
+GtkTree (so, remember to cast it using GTK_WIDGET (Tree) if you want
+to use one of the gtk_widget_*() functions on it).
+
+Instead of directly accessing the children field of a GtkTree widget,
+it's probably best to cast it using GTK_CONTAINER (Tree), and pass it
+to the gtk_container_children() function. This creates a duplicate of
+the original list, so it's advisable to free it up using g_list_free()
+after you're done with it, or to iterate on it destructively, like
+this:
<tscreen><verb>
-GtkWidget *gtk_list_new( void );
+ children = gtk_container_children (GTK_CONTAINER (tree));
+ while (children) {
+ do_something_nice (GTK_TREE_ITEM (children->data));
+ children = g_list_remove_link (children, children);
+}
</verb></tscreen>
-Create a new GtkList object. The new widget is returned as a pointer
-to a GtkWidget object. NULL is returned on failure.
+The <tt>tree_owner</tt> field is defined only in subtrees, where it
+points to the GtkTreeItem widget which holds the tree in question.
+The <tt>level</tt> field indicates how deeply nested a particular tree
+is; root trees have level 0, and each successive level of subtrees has
+a level one greater than the parent level. This field is set only
+after a GtkTree widget is actually mapped (i.e. drawn on the screen).
+<sect2> Signals<label id="sec_GtkTree_Signals">
+<p>
<tscreen><verb>
-void gtk_list_insert_items( GtkList *list,
- GList *items,
- gint position );
+void selection_changed( GtkTree *tree );
</verb></tscreen>
-Insert list items into the list, starting at <tt/position/.
-<tt/items/ is a doubly linked list where each nodes data pointer is
-expected to point to a newly created GtkListItem. The GList nodes of
-<tt/items/ are taken over by the list.
+This signal will be emitted whenever the <tt>selection</tt> field of a
+GtkTree has changed. This happens when a child of the GtkTree is
+selected or deselected.
<tscreen><verb>
-void gtk_list_append_items( GtkList *list,
- GList *items);
+void select_child( GtkTree *tree,
+ GtkWidget *child );
</verb></tscreen>
-Insert list items just like gtk_list_insert_items() at the end of the
-list. The GList nodes of <tt/items/ are taken over by the list.
+This signal is emitted when a child of the GtkTree is about to get
+selected. This happens on calls to gtk_tree_select_item(),
+gtk_tree_select_child(), on <em>all</em> button presses and calls to
+gtk_tree_item_toggle() and gtk_item_toggle(). It may sometimes be
+indirectly triggered on other occasions where children get added to or
+removed from the GtkTree.
<tscreen><verb>
-void gtk_list_prepend_items( GtkList *list,
- GList *items);
+void unselect_child (GtkTree *tree,
+ GtkWidget *child);
</verb></tscreen>
-Insert list items just like gtk_list_insert_items() at the very
-beginning of the list. The GList nodes of <tt/items/ are taken over by
-the list.
+This signal is emitted when a child of the GtkTree is about to get
+deselected. As of GTK+ 1.0.4, this seems to only occur on calls to
+gtk_tree_unselect_item() or gtk_tree_unselect_child(), and perhaps on
+other occasions, but <em>not</em> when a button press deselects a
+child, nor on emission of the "toggle" signal by gtk_item_toggle().
+<sect2> Functions and Macros<label id="sec_GtkTree_Functions">
+<p>
<tscreen><verb>
-void gtk_list_remove_items( GtkList *list,
- GList *items);
+guint gtk_tree_get_type( void );
</verb></tscreen>
-Remove list items from the list. <tt/items/ is a doubly linked list
-where each nodes data pointer is expected to point to a direct child
-of list. It is the callers responsibility to make a call to
-g_list_free(items) afterwards. Also the caller has to destroy the list
-items himself.
+Returns the `GtkTree' type identifier.
<tscreen><verb>
-void gtk_list_clear_items( GtkList *list,
- gint start,
- gint end );
+GtkWidget* gtk_tree_new( void );
</verb></tscreen>
-Remove and destroy list items from the list. A widget is affected if
-its current position within the list is in the range specified by
-<tt/start/ and <tt/end/.
+Create a new GtkTree object. The new widget is returned as a pointer
+to a GtkWidget object. NULL is returned on failure.
<tscreen><verb>
-void gtk_list_select_item( GtkList *list,
+void gtk_tree_append( GtkTree *tree,
+ GtkWidget *tree_item );
+</verb></tscreen>
+
+Append a tree item to a GtkTree.
+
+<tscreen><verb>
+void gtk_tree_prepend( GtkTree *tree,
+ GtkWidget *tree_item );
+</verb></tscreen>
+
+Prepend a tree item to a GtkTree.
+
+<tscreen><verb>
+void gtk_tree_insert( GtkTree *tree,
+ GtkWidget *tree_item,
+ gint position );
+</verb></tscreen>
+
+Insert a tree item into a GtkTree at the position in the list
+specified by <tt>position.</tt>
+
+<tscreen><verb>
+void gtk_tree_remove_items( GtkTree *tree,
+ GList *items );
+</verb></tscreen>
+
+Remove a list of items (in the form of a GList *) from a GtkTree.
+Note that removing an item from a tree dereferences (and thus usually)
+destroys it <em>and</em> its subtree, if it has one, <em>and</em> all
+subtrees in that subtree. If you want to remove only one item, you
+can use gtk_container_remove().
+
+<tscreen><verb>
+void gtk_tree_clear_items( GtkTree *tree,
+ gint start,
+ gint end );
+</verb></tscreen>
+
+Remove the items from position <tt>start</tt> to position <tt>end</tt>
+from a GtkTree. The same warning about dereferencing applies here, as
+gtk_tree_clear_items() simply constructs a list and passes it to
+gtk_tree_remove_items().
+
+<tscreen><verb>
+void gtk_tree_select_item( GtkTree *tree,
gint item );
</verb></tscreen>
-Invoke the select_child signal for a list item specified through its
-current position within the list.
+Emits the "select_item" signal for the child at position
+<tt>item</tt>, thus selecting the child (unless you unselect it in a
+signal handler).
<tscreen><verb>
-void gtk_list_unselect_item( GtkList *list,
- gint item);
+void gtk_tree_unselect_item( GtkTree *tree,
+ gint item );
</verb></tscreen>
-Invoke the unselect_child signal for a list item specified through its
-current position within the list.
+Emits the "unselect_item" signal for the child at position
+<tt>item</tt>, thus unselecting the child.
<tscreen><verb>
-void gtk_list_select_child( GtkList *list,
- GtkWidget *child);
+void gtk_tree_select_child( GtkTree *tree,
+ GtkWidget *tree_item );
</verb></tscreen>
-Invoke the select_child signal for the specified child.
+Emits the "select_item" signal for the child <tt>tree_item</tt>, thus
+selecting it.
<tscreen><verb>
-void gtk_list_unselect_child( GtkList *list,
- GtkWidget *child);
+void gtk_tree_unselect_child( GtkTree *tree,
+ GtkWidget *tree_item );
</verb></tscreen>
-Invoke the unselect_child signal for the specified child.
+Emits the "unselect_item" signal for the child <tt>tree_item</tt>,
+thus unselecting it.
<tscreen><verb>
-gint gtk_list_child_position( GtkList *list,
- GtkWidget *child);
+gint gtk_tree_child_position( GtkTree *tree,
+ GtkWidget *child );
</verb></tscreen>
-Return the position of <tt/child/ within the list. "-1" is returned on
-failure.
+Returns the position in the tree of <tt>child</tt>, unless
+<tt>child</tt> is not in the tree, in which case it returns -1.
<tscreen><verb>
-void gtk_list_set_selection_mode( GtkList *list,
- GtkSelectionMode mode );
+void gtk_tree_set_selection_mode( GtkTree *tree,
+ GtkSelectionMode mode );
</verb></tscreen>
-Set the selection mode MODE which can be of GTK_SELECTION_SINGLE,
-GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE or
-GTK_SELECTION_EXTENDED.
+Sets the selection mode, which can be one of GTK_SELECTION_SINGLE (the
+default), GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE, or
+GTK_SELECTION_EXTENDED. This is only defined for root trees, which
+makes sense, since the root tree "owns" the selection. Setting it for
+subtrees has no effect at all; the value is simply ignored.
<tscreen><verb>
-GtkList *GTK_LIST( gpointer obj );
+void gtk_tree_set_view_mode( GtkTree *tree,
+ GtkTreeViewMode mode );
</verb></tscreen>
-Cast a generic pointer to `GtkList *'. *Note Standard Macros::, for
-more info.
+Sets the "view mode", which can be either GTK_TREE_VIEW_LINE (the
+default) or GTK_TREE_VIEW_ITEM. The view mode propagates from a tree
+to its subtrees, and can't be set exclusively to a subtree (this is
+not exactly true - see the example code comments).
+
+The term "view mode" is rather ambiguous - basically, it controls the
+way the highlight is drawn when one of a tree's children is selected.
+If it's GTK_TREE_VIEW_LINE, the entire GtkTreeItem widget is
+highlighted, while for GTK_TREE_VIEW_ITEM, only the child widget
+(i.e. usually the label) is highlighted.
<tscreen><verb>
-GtkListClass *GTK_LIST_CLASS( gpointer class);
+void gtk_tree_set_view_lines( GtkTree *tree,
+ guint flag );
</verb></tscreen>
-Cast a generic pointer to `GtkListClass*'. *Note Standard Macros::,
-for more info.
+Controls whether connecting lines between tree items are drawn.
+<tt>flag</tt> is either TRUE, in which case they are, or FALSE, in
+which case they aren't.
<tscreen><verb>
-gint GTK_IS_LIST( gpointer obj);
+GtkTree *GTK_TREE (gpointer obj);
</verb></tscreen>
-Determine if a generic pointer refers to a `GtkList' object. *Note
-Standard Macros::, for more info.
+Cast a generic pointer to `GtkTree *'.
-<!-- ----------------------------------------------------------------- -->
-<sect1> Example
+<tscreen><verb>
+GtkTreeClass *GTK_TREE_CLASS (gpointer class);
+</verb></tscreen>
+
+Cast a generic pointer to `GtkTreeClass*'.
+
+<tscreen><verb>
+gint GTK_IS_TREE (gpointer obj);
+</verb></tscreen>
+
+Determine if a generic pointer refers to a `GtkTree' object.
+
+<tscreen><verb>
+gint GTK_IS_ROOT_TREE (gpointer obj)
+</verb></tscreen>
+
+Determine if a generic pointer refers to a `GtkTree' object
+<em>and</em> is a root tree. Though this will accept any pointer, the
+results of passing it a pointer that does not refer to a GtkTree are
+undefined and possibly harmful.
+
+<tscreen><verb>
+GtkTree *GTK_TREE_ROOT_TREE (gpointer obj)
+</verb></tscreen>
+
+Return the root tree of a pointer to a `GtkTree' object. The above
+warning applies.
+
+<tscreen><verb>
+GList *GTK_TREE_SELECTION( gpointer obj)
+</verb></tscreen>
+
+Return the selection list of the root tree of a `GtkTree' object. The
+above warning applies here, too.
+
+<sect1> Tree Item Widget<label id="sec_Tree_Item_Widget">
<p>
-Following is an example program that will print out the changes of the
-selection of a GtkList, and lets you "arrest" list items into a prison
-by selecting them with the rightmost mouse button.
+The GtkTreeItem widget, like GtkListItem, is derived from GtkItem,
+which in turn is derived from GtkBin. Therefore, the item itself is a
+generic container holding exactly one child widget, which can be of
+any type. The GtkTreeItem widget has a number of extra fields, but
+the only one we need be concerned with is the <tt>subtree</tt> field.
+
+The definition for the GtkTreeItem struct looks like this:
<tscreen><verb>
-/* example-start list list.c */
+struct _GtkTreeItem
+{
+ GtkItem item;
-/* Include the gtk+ header files
- * Include stdio.h, we need that for the printf() function
- */
-#include <gtk/gtk.h>
-#include <stdio.h>
+ GtkWidget *subtree;
+ GtkWidget *pixmaps_box;
+ GtkWidget *plus_pix_widget, *minus_pix_widget;
-/* This is our data identification string to store
- * data in list items
- */
-const gchar *list_item_data_key="list_item_data";
+ GList *pixmaps; /* pixmap node for this items color depth */
+ guint expanded : 1;
+};
+</verb></tscreen>
-/* prototypes for signal handler that we are going to connect
- * to the GtkList widget
- */
-static void sigh_print_selection( GtkWidget *gtklist,
- gpointer func_data);
+The <tt>pixmaps_box</tt> field is a GtkEventBox which catches clicks
+on the plus/minus symbol which controls expansion and collapsing. The
+<tt>pixmaps</tt> field points to an internal data structure. Since
+you can always obtain the subtree of a GtkTreeItem in a (relatively)
+type-safe manner with the GTK_TREE_ITEM_SUBTREE (Item) macro, it's
+probably advisable never to touch the insides of a GtkTreeItem unless
+you <em>really</em> know what you're doing.
-static void sigh_button_event( GtkWidget *gtklist,
- GdkEventButton *event,
- GtkWidget *frame );
+Since it is directly derived from a GtkItem it can be treated as such
+by using the GTK_ITEM (TreeItem) macro. A GtkTreeItem usually holds a
+label, so the convenience function gtk_list_item_new_with_label() is
+provided. The same effect can be achieved using code like the
+following, which is actually copied verbatim from
+gtk_tree_item_new_with_label():
+<tscreen><verb>
+tree_item = gtk_tree_item_new ();
+label_widget = gtk_label_new (label);
+gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
-/* Main function to set up the user interface */
+gtk_container_add (GTK_CONTAINER (tree_item), label_widget);
+gtk_widget_show (label_widget);
+</verb></tscreen>
-gint main (int argc,
- gchar *argv[])
-{
- GtkWidget *separator;
- GtkWidget *window;
- GtkWidget *vbox;
- GtkWidget *scrolled_window;
- GtkWidget *frame;
- GtkWidget *gtklist;
- GtkWidget *button;
- GtkWidget *list_item;
- GList *dlist;
- guint i;
- gchar buffer[64];
-
-
- /* Initialize gtk+ (and subsequently gdk) */
-
- gtk_init(&argc, &argv);
-
-
- /* Create a window to put all the widgets in
- * connect gtk_main_quit() to the "destroy" event of
- * the window to handle window manager close-window-events
- */
- window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_window_set_title(GTK_WINDOW(window), "GtkList Example");
- gtk_signal_connect(GTK_OBJECT(window),
- "destroy",
- GTK_SIGNAL_FUNC(gtk_main_quit),
- NULL);
-
-
- /* Inside the window we need a box to arrange the widgets
- * vertically */
- vbox=gtk_vbox_new(FALSE, 5);
- gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
- gtk_container_add(GTK_CONTAINER(window), vbox);
- gtk_widget_show(vbox);
-
- /* This is the scrolled window to put the GtkList widget inside */
- scrolled_window=gtk_scrolled_window_new(NULL, NULL);
- gtk_widget_set_usize(scrolled_window, 250, 150);
- gtk_container_add(GTK_CONTAINER(vbox), scrolled_window);
- gtk_widget_show(scrolled_window);
-
- /* Create the GtkList widget.
- * Connect the sigh_print_selection() signal handler
- * function to the "selection_changed" signal of the GtkList
- * to print out the selected items each time the selection
- * has changed */
- gtklist=gtk_list_new();
- gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window),
- gtklist);
- gtk_widget_show(gtklist);
- gtk_signal_connect(GTK_OBJECT(gtklist),
- "selection_changed",
- GTK_SIGNAL_FUNC(sigh_print_selection),
- NULL);
-
- /* We create a "Prison" to put a list item in ;) */
- frame=gtk_frame_new("Prison");
- gtk_widget_set_usize(frame, 200, 50);
- gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
- gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
- gtk_container_add(GTK_CONTAINER(vbox), frame);
- gtk_widget_show(frame);
-
- /* Connect the sigh_button_event() signal handler to the GtkList
- * which will handle the "arresting" of list items
- */
- gtk_signal_connect(GTK_OBJECT(gtklist),
- "button_release_event",
- GTK_SIGNAL_FUNC(sigh_button_event),
- frame);
-
- /* Create a separator */
- separator=gtk_hseparator_new();
- gtk_container_add(GTK_CONTAINER(vbox), separator);
- gtk_widget_show(separator);
-
- /* Finally create a button and connect it's "clicked" signal
- * to the destruction of the window */
- button=gtk_button_new_with_label("Close");
- gtk_container_add(GTK_CONTAINER(vbox), button);
- gtk_widget_show(button);
- gtk_signal_connect_object(GTK_OBJECT(button),
- "clicked",
- GTK_SIGNAL_FUNC(gtk_widget_destroy),
- GTK_OBJECT(window));
-
-
- /* Now we create 5 list items, each having it's own
- * label and add them to the GtkList using gtk_container_add()
- * Also we query the text string from the label and
- * associate it with the list_item_data_key for each list item
- */
- for (i=0; i<5; i++) {
- GtkWidget *label;
- gchar *string;
-
- sprintf(buffer, "ListItemContainer with Label #%d", i);
- label=gtk_label_new(buffer);
- list_item=gtk_list_item_new();
- gtk_container_add(GTK_CONTAINER(list_item), label);
- gtk_widget_show(label);
- gtk_container_add(GTK_CONTAINER(gtklist), list_item);
- gtk_widget_show(list_item);
- gtk_label_get(GTK_LABEL(label), &string);
- gtk_object_set_data(GTK_OBJECT(list_item),
- list_item_data_key,
- string);
- }
- /* Here, we are creating another 5 labels, this time
- * we use gtk_list_item_new_with_label() for the creation
- * we can't query the text string from the label because
- * we don't have the labels pointer and therefore
- * we just associate the list_item_data_key of each
- * list item with the same text string.
- * For adding of the list items we put them all into a doubly
- * linked list (GList), and then add them by a single call to
- * gtk_list_append_items().
- * Because we use g_list_prepend() to put the items into the
- * doubly linked list, their order will be descending (instead
- * of ascending when using g_list_append())
- */
- dlist=NULL;
- for (; i<10; i++) {
- sprintf(buffer, "List Item with Label %d", i);
- list_item=gtk_list_item_new_with_label(buffer);
- dlist=g_list_prepend(dlist, list_item);
- gtk_widget_show(list_item);
- gtk_object_set_data(GTK_OBJECT(list_item),
- list_item_data_key,
- "ListItem with integrated Label");
- }
- gtk_list_append_items(GTK_LIST(gtklist), dlist);
-
- /* Finally we want to see the window, don't we? ;) */
- gtk_widget_show(window);
-
- /* Fire up the main event loop of gtk */
- gtk_main();
-
- /* We get here after gtk_main_quit() has been called which
- * happens if the main window gets destroyed
- */
- return(0);
-}
-
-/* This is the signal handler that got connected to button
- * press/release events of the GtkList
- */
-void sigh_button_event( GtkWidget *gtklist,
- GdkEventButton *event,
- GtkWidget *frame )
-{
- /* We only do something if the third (rightmost mouse button
- * was released
- */
- if (event->type==GDK_BUTTON_RELEASE &&
- event->button==3) {
- GList *dlist, *free_list;
- GtkWidget *new_prisoner;
-
- /* Fetch the currently selected list item which
- * will be our next prisoner ;)
- */
- dlist=GTK_LIST(gtklist)->selection;
- if (dlist)
- new_prisoner=GTK_WIDGET(dlist->data);
- else
- new_prisoner=NULL;
-
- /* Look for already imprisoned list items, we
- * will put them back into the list.
- * Remember to free the doubly linked list that
- * gtk_container_children() returns
- */
- dlist=gtk_container_children(GTK_CONTAINER(frame));
- free_list=dlist;
- while (dlist) {
- GtkWidget *list_item;
-
- list_item=dlist->data;
-
- gtk_widget_reparent(list_item, gtklist);
-
- dlist=dlist->next;
- }
- g_list_free(free_list);
-
- /* If we have a new prisoner, remove him from the
- * GtkList and put him into the frame "Prison".
- * We need to unselect the item first.
- */
- if (new_prisoner) {
- GList static_dlist;
-
- static_dlist.data=new_prisoner;
- static_dlist.next=NULL;
- static_dlist.prev=NULL;
-
- gtk_list_unselect_child(GTK_LIST(gtklist),
- new_prisoner);
- gtk_widget_reparent(new_prisoner, frame);
- }
- }
-}
-
-/* This is the signal handler that gets called if GtkList
- * emits the "selection_changed" signal
- */
-void sigh_print_selection( GtkWidget *gtklist,
- gpointer func_data)
-{
- GList *dlist;
-
- /* Fetch the doubly linked list of selected items
- * of the GtkList, remember to treat this as read-only!
- */
- dlist=GTK_LIST(gtklist)->selection;
-
- /* If there are no selected items there is nothing more
- * to do than just telling the user so
- */
- if (!dlist) {
- g_print("Selection cleared\n");
- return;
- }
- /* Ok, we got a selection and so we print it
- */
- g_print("The selection is a ");
-
- /* Get the list item from the doubly linked list
- * and then query the data associated with list_item_data_key.
- * We then just print it */
- while (dlist) {
- GtkObject *list_item;
- gchar *item_data_string;
-
- list_item=GTK_OBJECT(dlist->data);
- item_data_string=gtk_object_get_data(list_item,
- list_item_data_key);
- g_print("%s ", item_data_string);
-
- dlist=dlist->next;
- }
- g_print("\n");
-}
-/* example-end */
-</verb></tscreen>
-
-<!-- ----------------------------------------------------------------- -->
-<sect1> List Item Widget
-<p>
-The GtkListItem widget is designed to act as a container holding up to
-one child, providing functions for selection/deselection just like the
-GtkList widget requires them for its children.
-
-A GtkListItem has its own window to receive events and has its own
-background color which is usually white.
-
-As it is directly derived from a GtkItem it can be treated as such by
-using the GTK_ITEM(ListItem) macro, see the GtkItem widget for more on
-this. Usually a GtkListItem just holds a label to identify e.g. a
-filename within a GtkList -- therefore the convenience function
-gtk_list_item_new_with_label() is provided. The same effect can be
-achieved by creating a GtkLabel on its own, setting its alignment to
-xalign=0 and yalign=0.5 with a subsequent container addition to the
-GtkListItem.
-
-As one is not forced to add a GtkLabel to a GtkListItem, you could
-also add a GtkVBox or a GtkArrow etc. to the GtkListItem.
-
-<!-- ----------------------------------------------------------------- -->
-<sect1> Signals
-<p>
-A GtkListItem does not create new signals on its own, but inherits
-the signals of a GtkItem. *Note GtkItem::, for more info.
-
-<!-- ----------------------------------------------------------------- -->
-<sect1> Functions
-<p>
-<tscreen><verb>
-guint gtk_list_item_get_type( void );
-</verb></tscreen>
-
-Returns the `GtkListItem' type identifier.
-
-<tscreen><verb>
-GtkWidget *gtk_list_item_new( void );
-</verb></tscreen>
-
-Create a new GtkListItem object. The new widget is returned as a
-pointer to a GtkWidget object. NULL is returned on failure.
-
-<tscreen><verb>
-GtkWidget *gtk_list_item_new_with_label( gchar *label );
-</verb></tscreen>
-
-Create a new GtkListItem object, having a single GtkLabel as the sole
-child. The new widget is returned as a pointer to a GtkWidget
-object. NULL is returned on failure.
-
-<tscreen><verb>
-void gtk_list_item_select( GtkListItem *list_item );
-</verb></tscreen>
-
-This function is basically a wrapper around a call to gtk_item_select
-(GTK_ITEM (list_item)) which will emit the select signal. *Note
-GtkItem::, for more info.
-
-<tscreen><verb>
-void gtk_list_item_deselect( GtkListItem *list_item );
-</verb></tscreen>
-
-This function is basically a wrapper around a call to
-gtk_item_deselect (GTK_ITEM (list_item)) which will emit the deselect
-signal. *Note GtkItem::, for more info.
-
-<tscreen><verb>
-GtkListItem *GTK_LIST_ITEM( gpointer obj );
-</verb></tscreen>
-
-Cast a generic pointer to `GtkListItem*'. *Note Standard Macros::, for
-more info.
-
-<tscreen><verb>
-GtkListItemClass *GTK_LIST_ITEM_CLASS( gpointer class );
-</verb></tscreen>
-
-Cast a generic pointer to GtkListItemClass*. *Note Standard Macros::,
-for more info.
-
-<tscreen><verb>
-gint GTK_IS_LIST_ITEM( gpointer obj );
-</verb></tscreen>
-
-Determine if a generic pointer refers to a `GtkListItem' object.
-*Note Standard Macros::, for more info.
-
-<!-- ----------------------------------------------------------------- -->
-<sect1> Example
-<p>
-Please see the GtkList example on this, which covers the usage of a
-GtkListItem as well.
-
-<!-- ***************************************************************** -->
-<sect> Tree Widget<label id="sec_Tree_Widgets">
-<!-- ***************************************************************** -->
-<p>
-The purpose of tree widgets is to display hierarchically-organized
-data. The GtkTree widget itself is a vertical container for widgets of
-type GtkTreeItem. GtkTree itself is not terribly different from
-GtkList - both are derived directly from GtkContainer, and the
-GtkContainer methods work in the same way on GtkTree widgets as on
-GtkList widgets. The difference is that GtkTree widgets can be nested
-within other GtkTree widgets. We'll see how to do this shortly.
-
-The GtkTree widget has its own window, and defaults to a white
-background, as does GtkList. Also, most of the GtkTree methods work in
-the same way as the corresponding GtkList ones. However, GtkTree is
-not derived from GtkList, so you cannot use them interchangeably.
-
-<sect1> Creating a Tree
-<p>
-A GtkTree is created in the usual way, using:
-
-<tscreen><verb>
-GtkWidget* gtk_tree_new( void );
-</verb></tscreen>
-
-Like the GtkList widget, a GtkTree will simply keep growing as more
-items are added to it, as well as when subtrees are expanded. For
-this reason, they are almost always packed into a
-GtkScrolledWindow. You might want to use gtk_widget_set_usize() on the
-scrolled window to ensure that it is big enough to see the tree's
-items, as the default size for GtkScrolledWindow is quite small.
-
-Now that you have a tree, you'll probably want to add some items to
-it. <ref id="sec_Tree_Item_Widget" name="The Tree Item Widget"> below
-explains the gory details of GtkTreeItem. For now, it'll suffice to
-create one, using:
-
-<tscreen><verb>
-GtkWidget* gtk_tree_item_new_with_label( gchar *label );
-</verb></tscreen>
-
-You can then add it to the tree using one of the following (see
-<ref id="sec_GtkTree_Functions" name="Functions and Macros">
-below for more options):
-
-<tscreen><verb>
-void gtk_tree_append( GtkTree *tree,
- GtkWidget *tree_item );
-
-void gtk_tree_prepend( GtkTree *tree,
- GtkWidget *tree_item );
-</verb></tscreen>
-
-Note that you must add items to a GtkTree one at a time - there is no
-equivalent to gtk_list_*_items().
-
-<!-- ----------------------------------------------------------------- -->
-<sect1> Adding a Subtree
-<p>
-A subtree is created like any other GtkTree widget. A subtree is added
-to another tree beneath a tree item, using:
-
-<tscreen><verb>
-void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
- GtkWidget *subtree );
-</verb></tscreen>
-
-You do not need to call gtk_widget_show() on a subtree before or after
-adding it to a GtkTreeItem. However, you <em>must</em> have added the
-GtkTreeItem in question to a parent tree before calling
-gtk_tree_item_set_subtree(). This is because, technically, the parent
-of the subtree is <em>not</em> the GtkTreeItem which "owns" it, but
-rather the GtkTree which holds that GtkTreeItem.
-
-When you add a subtree to a GtkTreeItem, a plus or minus sign appears
-beside it, which the user can click on to "expand" or "collapse" it,
-meaning, to show or hide its subtree. GtkTreeItems are collapsed by
-default. Note that when you collapse a GtkTreeItem, any selected
-items in its subtree remain selected, which may not be what the user
-expects.
-
-<!-- ----------------------------------------------------------------- -->
-<sect1> Handling the Selection List
-<p>
-As with GtkList, the GtkTree type has a <tt>selection</tt> field, and
-it is possible to control the behaviour of the tree (somewhat) by
-setting the selection type using:
-
-<tscreen><verb>
-void gtk_tree_set_selection_mode( GtkTree *tree,
- GtkSelectionMode mode );
-</verb></tscreen>
-
-The semantics associated with the various selection modes are
-described in the section on the GtkList widget. As with the GtkList
-widget, the "select_child", "unselect_child" (not really - see <ref
-id="sec_GtkTree_Signals" name="Signals"> below for an explanation),
-and "selection_changed" signals are emitted when list items are
-selected or unselected. However, in order to take advantage of these
-signals, you need to know <em>which</em> GtkTree widget they will be
-emitted by, and where to find the list of selected items.
-
-This is a source of potential confusion. The best way to explain this
-is that though all GtkTree widgets are created equal, some are more
-equal than others. All GtkTree widgets have their own X window, and
-can therefore receive events such as mouse clicks (if their
-GtkTreeItems or their children don't catch them first!). However, to
-make GTK_SELECTION_SINGLE and GTK_SELECTION_BROWSE selection types
-behave in a sane manner, the list of selected items is specific to the
-topmost GtkTree widget in a hierarchy, known as the "root tree".
-
-Thus, accessing the <tt>selection</tt>field directly in an arbitrary
-GtkTree widget is not a good idea unless you <em>know</em> it's the
-root tree. Instead, use the GTK_TREE_SELECTION (Tree) macro, which
-gives the root tree's selection list as a GList pointer. Of course,
-this list can include items that are not in the subtree in question if
-the selection type is GTK_SELECTION_MULTIPLE.
-
-Finally, the "select_child" (and "unselect_child", in theory) signals
-are emitted by all trees, but the "selection_changed" signal is only
-emitted by the root tree. Consequently, if you want to handle the
-"select_child" signal for a tree and all its subtrees, you will have
-to call gtk_signal_connect() for every subtree.
-
-<sect1> Tree Widget Internals
-<p>
-The GtkTree's struct definition looks like this:
-
-<tscreen><verb>
-struct _GtkTree
-{
- GtkContainer container;
-
- GList *children;
-
- GtkTree* root_tree; /* owner of selection list */
- GtkWidget* tree_owner;
- GList *selection;
- guint level;
- guint indent_value;
- guint current_indent;
- guint selection_mode : 2;
- guint view_mode : 1;
- guint view_line : 1;
-};
-</verb></tscreen>
-
-The perils associated with accessing the <tt>selection</tt> field
-directly have already been mentioned. The other important fields of
-the struct can also be accessed with handy macros or class functions.
-GTK_TREE_IS_ROOT_TREE (Tree) returns a boolean value which indicates
-whether a tree is the root tree in a GtkTree hierarchy, while
-GTK_TREE_ROOT_TREE (Tree) returns the root tree, an object of type
-GtkTree (so, remember to cast it using GTK_WIDGET (Tree) if you want
-to use one of the gtk_widget_*() functions on it).
-
-Instead of directly accessing the children field of a GtkTree widget,
-it's probably best to cast it using GTK_CONTAINER (Tree), and pass it
-to the gtk_container_children() function. This creates a duplicate of
-the original list, so it's advisable to free it up using g_list_free()
-after you're done with it, or to iterate on it destructively, like
-this:
-
-<tscreen><verb>
- children = gtk_container_children (GTK_CONTAINER (tree));
- while (children) {
- do_something_nice (GTK_TREE_ITEM (children->data));
- children = g_list_remove_link (children, children);
-}
-</verb></tscreen>
-
-The <tt>tree_owner</tt> field is defined only in subtrees, where it
-points to the GtkTreeItem widget which holds the tree in question.
-The <tt>level</tt> field indicates how deeply nested a particular tree
-is; root trees have level 0, and each successive level of subtrees has
-a level one greater than the parent level. This field is set only
-after a GtkTree widget is actually mapped (i.e. drawn on the screen).
-
-<sect2> Signals<label id="sec_GtkTree_Signals">
-<p>
-<tscreen><verb>
-void selection_changed( GtkTree *tree );
-</verb></tscreen>
-
-This signal will be emitted whenever the <tt>selection</tt> field of a
-GtkTree has changed. This happens when a child of the GtkTree is
-selected or deselected.
-
-<tscreen><verb>
-void select_child( GtkTree *tree,
- GtkWidget *child );
-</verb></tscreen>
-
-This signal is emitted when a child of the GtkTree is about to get
-selected. This happens on calls to gtk_tree_select_item(),
-gtk_tree_select_child(), on <em>all</em> button presses and calls to
-gtk_tree_item_toggle() and gtk_item_toggle(). It may sometimes be
-indirectly triggered on other occasions where children get added to or
-removed from the GtkTree.
-
-<tscreen><verb>
-void unselect_child (GtkTree *tree,
- GtkWidget *child);
-</verb></tscreen>
-
-This signal is emitted when a child of the GtkTree is about to get
-deselected. As of GTK+ 1.0.4, this seems to only occur on calls to
-gtk_tree_unselect_item() or gtk_tree_unselect_child(), and perhaps on
-other occasions, but <em>not</em> when a button press deselects a
-child, nor on emission of the "toggle" signal by gtk_item_toggle().
-
-<sect2> Functions and Macros<label id="sec_GtkTree_Functions">
-<p>
-<tscreen><verb>
-guint gtk_tree_get_type( void );
-</verb></tscreen>
-
-Returns the `GtkTree' type identifier.
-
-<tscreen><verb>
-GtkWidget* gtk_tree_new( void );
-</verb></tscreen>
-
-Create a new GtkTree object. The new widget is returned as a pointer
-to a GtkWidget object. NULL is returned on failure.
-
-<tscreen><verb>
-void gtk_tree_append( GtkTree *tree,
- GtkWidget *tree_item );
-</verb></tscreen>
-
-Append a tree item to a GtkTree.
-
-<tscreen><verb>
-void gtk_tree_prepend( GtkTree *tree,
- GtkWidget *tree_item );
-</verb></tscreen>
-
-Prepend a tree item to a GtkTree.
-
-<tscreen><verb>
-void gtk_tree_insert( GtkTree *tree,
- GtkWidget *tree_item,
- gint position );
-</verb></tscreen>
-
-Insert a tree item into a GtkTree at the position in the list
-specified by <tt>position.</tt>
-
-<tscreen><verb>
-void gtk_tree_remove_items( GtkTree *tree,
- GList *items );
-</verb></tscreen>
-
-Remove a list of items (in the form of a GList *) from a GtkTree.
-Note that removing an item from a tree dereferences (and thus usually)
-destroys it <em>and</em> its subtree, if it has one, <em>and</em> all
-subtrees in that subtree. If you want to remove only one item, you
-can use gtk_container_remove().
-
-<tscreen><verb>
-void gtk_tree_clear_items( GtkTree *tree,
- gint start,
- gint end );
-</verb></tscreen>
-
-Remove the items from position <tt>start</tt> to position <tt>end</tt>
-from a GtkTree. The same warning about dereferencing applies here, as
-gtk_tree_clear_items() simply constructs a list and passes it to
-gtk_tree_remove_items().
-
-<tscreen><verb>
-void gtk_tree_select_item( GtkTree *tree,
- gint item );
-</verb></tscreen>
-
-Emits the "select_item" signal for the child at position
-<tt>item</tt>, thus selecting the child (unless you unselect it in a
-signal handler).
-
-<tscreen><verb>
-void gtk_tree_unselect_item( GtkTree *tree,
- gint item );
-</verb></tscreen>
-
-Emits the "unselect_item" signal for the child at position
-<tt>item</tt>, thus unselecting the child.
-
-<tscreen><verb>
-void gtk_tree_select_child( GtkTree *tree,
- GtkWidget *tree_item );
-</verb></tscreen>
-
-Emits the "select_item" signal for the child <tt>tree_item</tt>, thus
-selecting it.
-
-<tscreen><verb>
-void gtk_tree_unselect_child( GtkTree *tree,
- GtkWidget *tree_item );
-</verb></tscreen>
-
-Emits the "unselect_item" signal for the child <tt>tree_item</tt>,
-thus unselecting it.
-
-<tscreen><verb>
-gint gtk_tree_child_position( GtkTree *tree,
- GtkWidget *child );
-</verb></tscreen>
-
-Returns the position in the tree of <tt>child</tt>, unless
-<tt>child</tt> is not in the tree, in which case it returns -1.
-
-<tscreen><verb>
-void gtk_tree_set_selection_mode( GtkTree *tree,
- GtkSelectionMode mode );
-</verb></tscreen>
-
-Sets the selection mode, which can be one of GTK_SELECTION_SINGLE (the
-default), GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE, or
-GTK_SELECTION_EXTENDED. This is only defined for root trees, which
-makes sense, since the root tree "owns" the selection. Setting it for
-subtrees has no effect at all; the value is simply ignored.
-
-<tscreen><verb>
-void gtk_tree_set_view_mode( GtkTree *tree,
- GtkTreeViewMode mode );
-</verb></tscreen>
-
-Sets the "view mode", which can be either GTK_TREE_VIEW_LINE (the
-default) or GTK_TREE_VIEW_ITEM. The view mode propagates from a tree
-to its subtrees, and can't be set exclusively to a subtree (this is
-not exactly true - see the example code comments).
-
-The term "view mode" is rather ambiguous - basically, it controls the
-way the highlight is drawn when one of a tree's children is selected.
-If it's GTK_TREE_VIEW_LINE, the entire GtkTreeItem widget is
-highlighted, while for GTK_TREE_VIEW_ITEM, only the child widget
-(i.e. usually the label) is highlighted.
-
-<tscreen><verb>
-void gtk_tree_set_view_lines( GtkTree *tree,
- guint flag );
-</verb></tscreen>
-
-Controls whether connecting lines between tree items are drawn.
-<tt>flag</tt> is either TRUE, in which case they are, or FALSE, in
-which case they aren't.
-
-<tscreen><verb>
-GtkTree *GTK_TREE (gpointer obj);
-</verb></tscreen>
-
-Cast a generic pointer to `GtkTree *'.
-
-<tscreen><verb>
-GtkTreeClass *GTK_TREE_CLASS (gpointer class);
-</verb></tscreen>
-
-Cast a generic pointer to `GtkTreeClass*'.
-
-<tscreen><verb>
-gint GTK_IS_TREE (gpointer obj);
-</verb></tscreen>
-
-Determine if a generic pointer refers to a `GtkTree' object.
-
-<tscreen><verb>
-gint GTK_IS_ROOT_TREE (gpointer obj)
-</verb></tscreen>
-
-Determine if a generic pointer refers to a `GtkTree' object
-<em>and</em> is a root tree. Though this will accept any pointer, the
-results of passing it a pointer that does not refer to a GtkTree are
-undefined and possibly harmful.
-
-<tscreen><verb>
-GtkTree *GTK_TREE_ROOT_TREE (gpointer obj)
-</verb></tscreen>
-
-Return the root tree of a pointer to a `GtkTree' object. The above
-warning applies.
-
-<tscreen><verb>
-GList *GTK_TREE_SELECTION( gpointer obj)
-</verb></tscreen>
-
-Return the selection list of the root tree of a `GtkTree' object. The
-above warning applies here, too.
-
-<sect1> Tree Item Widget<label id="sec_Tree_Item_Widget">
-<p>
-The GtkTreeItem widget, like GtkListItem, is derived from GtkItem,
-which in turn is derived from GtkBin. Therefore, the item itself is a
-generic container holding exactly one child widget, which can be of
-any type. The GtkTreeItem widget has a number of extra fields, but
-the only one we need be concerned with is the <tt>subtree</tt> field.
-
-The definition for the GtkTreeItem struct looks like this:
-
-<tscreen><verb>
-struct _GtkTreeItem
-{
- GtkItem item;
-
- GtkWidget *subtree;
- GtkWidget *pixmaps_box;
- GtkWidget *plus_pix_widget, *minus_pix_widget;
-
- GList *pixmaps; /* pixmap node for this items color depth */
-
- guint expanded : 1;
-};
-</verb></tscreen>
-
-The <tt>pixmaps_box</tt> field is a GtkEventBox which catches clicks
-on the plus/minus symbol which controls expansion and collapsing. The
-<tt>pixmaps</tt> field points to an internal data structure. Since
-you can always obtain the subtree of a GtkTreeItem in a (relatively)
-type-safe manner with the GTK_TREE_ITEM_SUBTREE (Item) macro, it's
-probably advisable never to touch the insides of a GtkTreeItem unless
-you <em>really</em> know what you're doing.
-
-Since it is directly derived from a GtkItem it can be treated as such
-by using the GTK_ITEM (TreeItem) macro. A GtkTreeItem usually holds a
-label, so the convenience function gtk_list_item_new_with_label() is
-provided. The same effect can be achieved using code like the
-following, which is actually copied verbatim from
-gtk_tree_item_new_with_label():
-
-<tscreen><verb>
-tree_item = gtk_tree_item_new ();
-label_widget = gtk_label_new (label);
-gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
-
-gtk_container_add (GTK_CONTAINER (tree_item), label_widget);
-gtk_widget_show (label_widget);
-</verb></tscreen>
-
-As one is not forced to add a GtkLabel to a GtkTreeItem, you could
-also add a GtkHBox or a GtkArrow, or even a GtkNotebook (though your
-app will likely be quite unpopular in this case) to the GtkTreeItem.
+As one is not forced to add a GtkLabel to a GtkTreeItem, you could
+also add a GtkHBox or a GtkArrow, or even a GtkNotebook (though your
+app will likely be quite unpopular in this case) to the GtkTreeItem.
If you remove all the items from a subtree, it will be destroyed and
unparented, unless you reference it beforehand, and the GtkTreeItem
<sect1> Drawing Area
<p>
<!-- ----------------------------------------------------------------- -->
-<sect1> Fixed Container
-<p>
-<!-- ----------------------------------------------------------------- -->
-<sect1> Frame
-<p>
-<!-- ----------------------------------------------------------------- -->
<sect1> Font Selection Dialog
<p>
<!-- ----------------------------------------------------------------- -->
data types, which allows it to be cast to a specific
event data type within a signal handler.
-<!-- Just a big list for now, needs expanding upon - TRG -->
-So, the event data types are defined as follows:
+<!-- Just a big list for now, needs expanding upon - TRG -->
+So, the event data types are defined as follows:
+
+<tscreen><verb>
+struct _GdkEventAny
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+};
+
+struct _GdkEventExpose
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ GdkRectangle area;
+ gint count; /* If non-zero, how many more events follow. */
+};
+
+struct _GdkEventNoExpose
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ /* XXX: does anyone need the X major_code or minor_code fields? */
+};
+
+struct _GdkEventVisibility
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ GdkVisibilityState state;
+};
+
+struct _GdkEventMotion
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ guint32 time;
+ gdouble x;
+ gdouble y;
+ gdouble pressure;
+ gdouble xtilt;
+ gdouble ytilt;
+ guint state;
+ gint16 is_hint;
+ GdkInputSource source;
+ guint32 deviceid;
+ gdouble x_root, y_root;
+};
+
+struct _GdkEventButton
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ guint32 time;
+ gdouble x;
+ gdouble y;
+ gdouble pressure;
+ gdouble xtilt;
+ gdouble ytilt;
+ guint state;
+ guint button;
+ GdkInputSource source;
+ guint32 deviceid;
+ gdouble x_root, y_root;
+};
+
+struct _GdkEventKey
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ guint32 time;
+ guint state;
+ guint keyval;
+ gint length;
+ gchar *string;
+};
+
+struct _GdkEventCrossing
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ GdkWindow *subwindow;
+ GdkNotifyType detail;
+};
+
+struct _GdkEventFocus
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ gint16 in;
+};
+
+struct _GdkEventConfigure
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ gint16 x, y;
+ gint16 width;
+ gint16 height;
+};
+
+struct _GdkEventProperty
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ GdkAtom atom;
+ guint32 time;
+ guint state;
+};
+
+struct _GdkEventSelection
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ GdkAtom selection;
+ GdkAtom target;
+ GdkAtom property;
+ guint32 requestor;
+ guint32 time;
+};
+
+/* This event type will be used pretty rarely. It only is important
+ for XInput aware programs that are drawing their own cursor */
+
+struct _GdkEventProximity
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ guint32 time;
+ GdkInputSource source;
+ guint32 deviceid;
+};
+
+struct _GdkEventDragRequest
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ guint32 requestor;
+ union {
+ struct {
+ guint protocol_version:4;
+ guint sendreply:1;
+ guint willaccept:1;
+ guint delete_data:1; /* Do *not* delete if link is sent, only
+ if data is sent */
+ guint senddata:1;
+ guint reserved:22;
+ } flags;
+ glong allflags;
+ } u;
+ guint8 isdrop; /* This gdk event can be generated by a couple of
+ X events - this lets the app know whether the
+ drop really occurred or we just set the data */
+
+ GdkPoint drop_coords;
+ gchar *data_type;
+ guint32 timestamp;
+};
-<tscreen><verb>
-struct _GdkEventAny
+struct _GdkEventDragBegin
{
GdkEventType type;
GdkWindow *window;
gint8 send_event;
+ union {
+ struct {
+ guint protocol_version:4;
+ guint reserved:28;
+ } flags;
+ glong allflags;
+ } u;
};
-struct _GdkEventExpose
+struct _GdkEventDropEnter
{
GdkEventType type;
GdkWindow *window;
gint8 send_event;
- GdkRectangle area;
- gint count; /* If non-zero, how many more events follow. */
+ guint32 requestor;
+ union {
+ struct {
+ guint protocol_version:4;
+ guint sendreply:1;
+ guint extended_typelist:1;
+ guint reserved:26;
+ } flags;
+ glong allflags;
+ } u;
};
-struct _GdkEventNoExpose
+struct _GdkEventDropLeave
{
GdkEventType type;
GdkWindow *window;
gint8 send_event;
- /* XXX: does anyone need the X major_code or minor_code fields? */
+ guint32 requestor;
+ union {
+ struct {
+ guint protocol_version:4;
+ guint reserved:28;
+ } flags;
+ glong allflags;
+ } u;
};
-struct _GdkEventVisibility
+struct _GdkEventDropDataAvailable
{
GdkEventType type;
GdkWindow *window;
gint8 send_event;
- GdkVisibilityState state;
+ guint32 requestor;
+ union {
+ struct {
+ guint protocol_version:4;
+ guint isdrop:1;
+ guint reserved:25;
+ } flags;
+ glong allflags;
+ } u;
+ gchar *data_type; /* MIME type */
+ gulong data_numbytes;
+ gpointer data;
+ guint32 timestamp;
+ GdkPoint coords;
};
-struct _GdkEventMotion
+struct _GdkEventClient
{
GdkEventType type;
GdkWindow *window;
gint8 send_event;
- guint32 time;
- gdouble x;
- gdouble y;
- gdouble pressure;
- gdouble xtilt;
- gdouble ytilt;
- guint state;
- gint16 is_hint;
- GdkInputSource source;
- guint32 deviceid;
- gdouble x_root, y_root;
+ GdkAtom message_type;
+ gushort data_format;
+ union {
+ char b[20];
+ short s[10];
+ long l[5];
+ } data;
};
-struct _GdkEventButton
+struct _GdkEventOther
{
GdkEventType type;
GdkWindow *window;
gint8 send_event;
- guint32 time;
- gdouble x;
- gdouble y;
- gdouble pressure;
- gdouble xtilt;
- gdouble ytilt;
- guint state;
- guint button;
- GdkInputSource source;
- guint32 deviceid;
- gdouble x_root, y_root;
+ GdkXEvent *xevent;
+};
+</verb></tscreen>
+
+<!-- ***************************************************************** -->
+<sect> Code Examples
+<!-- ***************************************************************** -->
+<p>
+Below are the code examples that are used in the above text
+which are not included in complete form elsewhere.
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>Tictactoe
+<!-- ----------------------------------------------------------------- -->
+<sect2>tictactoe.h
+<p>
+<tscreen><verb>
+/* example-start tictactoe tictactoe.h */
+
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __TICTACTOE_H__
+#define __TICTACTOE_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkvbox.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define TICTACTOE(obj) GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
+#define TICTACTOE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
+#define IS_TICTACTOE(obj) GTK_CHECK_TYPE (obj, tictactoe_get_type ())
+
+
+typedef struct _Tictactoe Tictactoe;
+typedef struct _TictactoeClass TictactoeClass;
+
+struct _Tictactoe
+{
+ GtkVBox vbox;
+
+ GtkWidget *buttons[3][3];
+};
+
+struct _TictactoeClass
+{
+ GtkVBoxClass parent_class;
+
+ void (* tictactoe) (Tictactoe *ttt);
+};
+
+guint tictactoe_get_type (void);
+GtkWidget* tictactoe_new (void);
+void tictactoe_clear (Tictactoe *ttt);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __TICTACTOE_H__ */
+
+/* example-end */
+</verb></tscreen>
+
+<!-- ----------------------------------------------------------------- -->
+<sect2>tictactoe.c
+<p>
+<tscreen><verb>
+/* example-start tictactoe tictactoe.c */
+
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gtk/gtksignal.h"
+#include "gtk/gtktable.h"
+#include "gtk/gtktogglebutton.h"
+#include "tictactoe.h"
+
+enum {
+ TICTACTOE_SIGNAL,
+ LAST_SIGNAL
};
-struct _GdkEventKey
+static void tictactoe_class_init (TictactoeClass *klass);
+static void tictactoe_init (Tictactoe *ttt);
+static void tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt);
+
+static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
+
+guint
+tictactoe_get_type ()
+{
+ static guint ttt_type = 0;
+
+ if (!ttt_type)
+ {
+ GtkTypeInfo ttt_info =
+ {
+ "Tictactoe",
+ sizeof (Tictactoe),
+ sizeof (TictactoeClass),
+ (GtkClassInitFunc) tictactoe_class_init,
+ (GtkObjectInitFunc) tictactoe_init,
+ (GtkArgSetFunc) NULL,
+ (GtkArgGetFunc) NULL
+ };
+
+ ttt_type = gtk_type_unique (gtk_vbox_get_type (), &ttt_info);
+ }
+
+ return ttt_type;
+}
+
+static void
+tictactoe_class_init (TictactoeClass *class)
{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- guint32 time;
- guint state;
- guint keyval;
- gint length;
- gchar *string;
-};
+ GtkObjectClass *object_class;
-struct _GdkEventCrossing
-{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- GdkWindow *subwindow;
- GdkNotifyType detail;
-};
+ object_class = (GtkObjectClass*) class;
+
+ tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),
+ gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
-struct _GdkEventFocus
-{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- gint16 in;
-};
-struct _GdkEventConfigure
-{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- gint16 x, y;
- gint16 width;
- gint16 height;
-};
+ gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
-struct _GdkEventProperty
-{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- GdkAtom atom;
- guint32 time;
- guint state;
-};
+ class->tictactoe = NULL;
+}
-struct _GdkEventSelection
+static void
+tictactoe_init (Tictactoe *ttt)
{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- GdkAtom selection;
- GdkAtom target;
- GdkAtom property;
- guint32 requestor;
- guint32 time;
-};
+ GtkWidget *table;
+ gint i,j;
+
+ table = gtk_table_new (3, 3, TRUE);
+ gtk_container_add (GTK_CONTAINER(ttt), table);
+ gtk_widget_show (table);
-/* This event type will be used pretty rarely. It only is important
- for XInput aware programs that are drawing their own cursor */
+ for (i=0;i<3; i++)
+ for (j=0;j<3; j++)
+ {
+ ttt->buttons[i][j] = gtk_toggle_button_new ();
+ gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j],
+ i, i+1, j, j+1);
+ gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
+ GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
+ gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
+ gtk_widget_show (ttt->buttons[i][j]);
+ }
+}
-struct _GdkEventProximity
+GtkWidget*
+tictactoe_new ()
{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- guint32 time;
- GdkInputSource source;
- guint32 deviceid;
-};
+ return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
+}
-struct _GdkEventDragRequest
+void
+tictactoe_clear (Tictactoe *ttt)
{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- guint32 requestor;
- union {
- struct {
- guint protocol_version:4;
- guint sendreply:1;
- guint willaccept:1;
- guint delete_data:1; /* Do *not* delete if link is sent, only
- if data is sent */
- guint senddata:1;
- guint reserved:22;
- } flags;
- glong allflags;
- } u;
- guint8 isdrop; /* This gdk event can be generated by a couple of
- X events - this lets the app know whether the
- drop really occurred or we just set the data */
+ int i,j;
- GdkPoint drop_coords;
- gchar *data_type;
- guint32 timestamp;
-};
+ for (i=0;i<3;i++)
+ for (j=0;j<3;j++)
+ {
+ gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
+ FALSE);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
+ }
+}
-struct _GdkEventDragBegin
+static void
+tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- union {
- struct {
- guint protocol_version:4;
- guint reserved:28;
- } flags;
- glong allflags;
- } u;
-};
+ int i,k;
-struct _GdkEventDropEnter
-{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- guint32 requestor;
- union {
- struct {
- guint protocol_version:4;
- guint sendreply:1;
- guint extended_typelist:1;
- guint reserved:26;
- } flags;
- glong allflags;
- } u;
-};
+ static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
+ { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
+ { 0, 1, 2 }, { 0, 1, 2 } };
+ static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
+ { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
+ { 0, 1, 2 }, { 2, 1, 0 } };
-struct _GdkEventDropLeave
-{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- guint32 requestor;
- union {
- struct {
- guint protocol_version:4;
- guint reserved:28;
- } flags;
- glong allflags;
- } u;
-};
+ int success, found;
-struct _GdkEventDropDataAvailable
-{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- guint32 requestor;
- union {
- struct {
- guint protocol_version:4;
- guint isdrop:1;
- guint reserved:25;
- } flags;
- glong allflags;
- } u;
- gchar *data_type; /* MIME type */
- gulong data_numbytes;
- gpointer data;
- guint32 timestamp;
- GdkPoint coords;
-};
+ for (k=0; k<8; k++)
+ {
+ success = TRUE;
+ found = FALSE;
-struct _GdkEventClient
-{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- GdkAtom message_type;
- gushort data_format;
- union {
- char b[20];
- short s[10];
- long l[5];
- } data;
-};
+ for (i=0;i<3;i++)
+ {
+ success = success &&
+ GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
+ found = found ||
+ ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
+ }
+
+ if (success && found)
+ {
+ gtk_signal_emit (GTK_OBJECT (ttt),
+ tictactoe_signals[TICTACTOE_SIGNAL]);
+ break;
+ }
+ }
+}
+
+/* example-end */
+</verb></tscreen>
+
+<!-- ----------------------------------------------------------------- -->
+<sect2>ttt_test.c
+<p>
+<tscreen><verb>
+/* example-start tictactoe ttt_test.c */
+
+#include <gtk/gtk.h>
+#include "tictactoe.h"
+
+void
+win (GtkWidget *widget, gpointer data)
+{
+ g_print ("Yay!\n");
+ tictactoe_clear (TICTACTOE (widget));
+}
-struct _GdkEventOther
+int
+main (int argc, char *argv[])
{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- GdkXEvent *xevent;
-};
-</verb></tscreen>
+ GtkWidget *window;
+ GtkWidget *ttt;
+
+ gtk_init (&argc, &argv);
-<!-- ***************************************************************** -->
-<sect> Code Examples
-<!-- ***************************************************************** -->
-<p>
-Below are the code examples that are used in the above text
-which are not included in complete form elsewhere.
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ GTK_SIGNAL_FUNC (gtk_exit), NULL);
+
+ gtk_container_set_border_width (GTK_CONTAINER (window), 10);
+
+ ttt = tictactoe_new ();
+
+ gtk_container_add (GTK_CONTAINER (window), ttt);
+ gtk_widget_show (ttt);
+
+ gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
+ GTK_SIGNAL_FUNC (win), NULL);
+
+ gtk_widget_show (window);
+
+ gtk_main ();
+
+ return 0;
+}
+
+/* example-end */
+</verb></tscreen>
<!-- ----------------------------------------------------------------- -->
-<sect1>Tictactoe
+<sect1> GtkDial
+
<!-- ----------------------------------------------------------------- -->
-<sect2>tictactoe.h
+<sect2> gtkdial.h
<p>
<tscreen><verb>
-/* example-start tictactoe tictactoe.h */
+/* example-start gtkdial gtkdial.h */
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
-#ifndef __TICTACTOE_H__
-#define __TICTACTOE_H__
+#ifndef __GTK_DIAL_H__
+#define __GTK_DIAL_H__
#include <gdk/gdk.h>
-#include <gtk/gtkvbox.h>
+#include <gtk/gtkadjustment.h>
+#include <gtk/gtkwidget.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
-#define TICTACTOE(obj) GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
-#define TICTACTOE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
-#define IS_TICTACTOE(obj) GTK_CHECK_TYPE (obj, tictactoe_get_type ())
+#define GTK_DIAL(obj) GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
+#define GTK_DIAL_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
+#define GTK_IS_DIAL(obj) GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
-typedef struct _Tictactoe Tictactoe;
-typedef struct _TictactoeClass TictactoeClass;
-struct _Tictactoe
+typedef struct _GtkDial GtkDial;
+typedef struct _GtkDialClass GtkDialClass;
+
+struct _GtkDial
{
- GtkVBox vbox;
-
- GtkWidget *buttons[3][3];
+ GtkWidget widget;
+
+ /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
+ guint policy : 2;
+
+ /* Button currently pressed or 0 if none */
+ guint8 button;
+
+ /* Dimensions of dial components */
+ gint radius;
+ gint pointer_width;
+
+ /* ID of update timer, or 0 if none */
+ guint32 timer;
+
+ /* Current angle */
+ gfloat angle;
+
+ /* Old values from adjustment stored so we know when something changes */
+ gfloat old_value;
+ gfloat old_lower;
+ gfloat old_upper;
+
+ /* The adjustment object that stores the data for this dial */
+ GtkAdjustment *adjustment;
};
-struct _TictactoeClass
+struct _GtkDialClass
{
- GtkVBoxClass parent_class;
-
- void (* tictactoe) (Tictactoe *ttt);
+ GtkWidgetClass parent_class;
};
-guint tictactoe_get_type (void);
-GtkWidget* tictactoe_new (void);
-void tictactoe_clear (Tictactoe *ttt);
+GtkWidget* gtk_dial_new (GtkAdjustment *adjustment);
+guint gtk_dial_get_type (void);
+GtkAdjustment* gtk_dial_get_adjustment (GtkDial *dial);
+void gtk_dial_set_update_policy (GtkDial *dial,
+ GtkUpdateType policy);
+
+void gtk_dial_set_adjustment (GtkDial *dial,
+ GtkAdjustment *adjustment);
#ifdef __cplusplus
}
#endif /* __cplusplus */
-#endif /* __TICTACTOE_H__ */
+#endif /* __GTK_DIAL_H__ */
/* example-end */
</verb></tscreen>
<!-- ----------------------------------------------------------------- -->
-<sect2>tictactoe.c
+<sect2> gtkdial.c
<p>
<tscreen><verb>
-/* example-start tictactoe tictactoe.c */
+/* example-start gtkdial gtkdial.c */
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
-#include "gtk/gtksignal.h"
-#include "gtk/gtktable.h"
-#include "gtk/gtktogglebutton.h"
-#include "tictactoe.h"
+#include <math.h>
+#include <stdio.h>
+#include <gtk/gtkmain.h>
+#include <gtk/gtksignal.h>
-enum {
- TICTACTOE_SIGNAL,
- LAST_SIGNAL
-};
+#include "gtkdial.h"
-static void tictactoe_class_init (TictactoeClass *klass);
-static void tictactoe_init (Tictactoe *ttt);
-static void tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt);
+#define SCROLL_DELAY_LENGTH 300
+#define DIAL_DEFAULT_SIZE 100
-static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
+/* Forward declarations */
+
+static void gtk_dial_class_init (GtkDialClass *klass);
+static void gtk_dial_init (GtkDial *dial);
+static void gtk_dial_destroy (GtkObject *object);
+static void gtk_dial_realize (GtkWidget *widget);
+static void gtk_dial_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_dial_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static gint gtk_dial_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static gint gtk_dial_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_dial_button_release (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_dial_motion_notify (GtkWidget *widget,
+ GdkEventMotion *event);
+static gint gtk_dial_timer (GtkDial *dial);
+
+static void gtk_dial_update_mouse (GtkDial *dial, gint x, gint y);
+static void gtk_dial_update (GtkDial *dial);
+static void gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
+ gpointer data);
+static void gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
+ gpointer data);
+
+/* Local data */
+
+static GtkWidgetClass *parent_class = NULL;
guint
-tictactoe_get_type ()
+gtk_dial_get_type ()
{
- static guint ttt_type = 0;
+ static guint dial_type = 0;
- if (!ttt_type)
+ if (!dial_type)
{
- GtkTypeInfo ttt_info =
+ GtkTypeInfo dial_info =
{
- "Tictactoe",
- sizeof (Tictactoe),
- sizeof (TictactoeClass),
- (GtkClassInitFunc) tictactoe_class_init,
- (GtkObjectInitFunc) tictactoe_init,
- (GtkArgSetFunc) NULL,
- (GtkArgGetFunc) NULL
+ "GtkDial",
+ sizeof (GtkDial),
+ sizeof (GtkDialClass),
+ (GtkClassInitFunc) gtk_dial_class_init,
+ (GtkObjectInitFunc) gtk_dial_init,
+ (GtkArgSetFunc) NULL,
+ (GtkArgGetFunc) NULL,
};
- ttt_type = gtk_type_unique (gtk_vbox_get_type (), &ttt_info);
+ dial_type = gtk_type_unique (gtk_widget_get_type (), &dial_info);
}
- return ttt_type;
+ return dial_type;
}
static void
-tictactoe_class_init (TictactoeClass *class)
+gtk_dial_class_init (GtkDialClass *class)
{
GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+
+ parent_class = gtk_type_class (gtk_widget_get_type ());
+
+ object_class->destroy = gtk_dial_destroy;
+
+ widget_class->realize = gtk_dial_realize;
+ widget_class->expose_event = gtk_dial_expose;
+ widget_class->size_request = gtk_dial_size_request;
+ widget_class->size_allocate = gtk_dial_size_allocate;
+ widget_class->button_press_event = gtk_dial_button_press;
+ widget_class->button_release_event = gtk_dial_button_release;
+ widget_class->motion_notify_event = gtk_dial_motion_notify;
+}
+
+static void
+gtk_dial_init (GtkDial *dial)
+{
+ dial->button = 0;
+ dial->policy = GTK_UPDATE_CONTINUOUS;
+ dial->timer = 0;
+ dial->radius = 0;
+ dial->pointer_width = 0;
+ dial->angle = 0.0;
+ dial->old_value = 0.0;
+ dial->old_lower = 0.0;
+ dial->old_upper = 0.0;
+ dial->adjustment = NULL;
+}
+
+GtkWidget*
+gtk_dial_new (GtkAdjustment *adjustment)
+{
+ GtkDial *dial;
+
+ dial = gtk_type_new (gtk_dial_get_type ());
+
+ if (!adjustment)
+ adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+
+ gtk_dial_set_adjustment (dial, adjustment);
+
+ return GTK_WIDGET (dial);
+}
+
+static void
+gtk_dial_destroy (GtkObject *object)
+{
+ GtkDial *dial;
- object_class = (GtkObjectClass*) class;
-
- tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
- GTK_RUN_FIRST,
- object_class->type,
- GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),
- gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_DIAL (object));
+ dial = GTK_DIAL (object);
- gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
+ if (dial->adjustment)
+ gtk_object_unref (GTK_OBJECT (dial->adjustment));
- class->tictactoe = NULL;
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
}
-static void
-tictactoe_init (Tictactoe *ttt)
+GtkAdjustment*
+gtk_dial_get_adjustment (GtkDial *dial)
{
- GtkWidget *table;
- gint i,j;
-
- table = gtk_table_new (3, 3, TRUE);
- gtk_container_add (GTK_CONTAINER(ttt), table);
- gtk_widget_show (table);
+ g_return_val_if_fail (dial != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
- for (i=0;i<3; i++)
- for (j=0;j<3; j++)
- {
- ttt->buttons[i][j] = gtk_toggle_button_new ();
- gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j],
- i, i+1, j, j+1);
- gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
- GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
- gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
- gtk_widget_show (ttt->buttons[i][j]);
- }
+ return dial->adjustment;
}
-GtkWidget*
-tictactoe_new ()
+void
+gtk_dial_set_update_policy (GtkDial *dial,
+ GtkUpdateType policy)
{
- return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
+ g_return_if_fail (dial != NULL);
+ g_return_if_fail (GTK_IS_DIAL (dial));
+
+ dial->policy = policy;
}
-void
-tictactoe_clear (Tictactoe *ttt)
+void
+gtk_dial_set_adjustment (GtkDial *dial,
+ GtkAdjustment *adjustment)
{
- int i,j;
+ g_return_if_fail (dial != NULL);
+ g_return_if_fail (GTK_IS_DIAL (dial));
- for (i=0;i<3;i++)
- for (j=0;j<3;j++)
- {
- gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
- FALSE);
- gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
- }
+ if (dial->adjustment)
+ {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
+ gtk_object_unref (GTK_OBJECT (dial->adjustment));
+ }
+
+ dial->adjustment = adjustment;
+ gtk_object_ref (GTK_OBJECT (dial->adjustment));
+
+ gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
+ (GtkSignalFunc) gtk_dial_adjustment_changed,
+ (gpointer) dial);
+ gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+ (GtkSignalFunc) gtk_dial_adjustment_value_changed,
+ (gpointer) dial);
+
+ dial->old_value = adjustment->value;
+ dial->old_lower = adjustment->lower;
+ dial->old_upper = adjustment->upper;
+
+ gtk_dial_update (dial);
}
static void
-tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
+gtk_dial_realize (GtkWidget *widget)
{
- int i,k;
+ GtkDial *dial;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
- static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
- { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
- { 0, 1, 2 }, { 0, 1, 2 } };
- static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
- { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
- { 0, 1, 2 }, { 2, 1, 0 } };
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_DIAL (widget));
- int success, found;
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+ dial = GTK_DIAL (widget);
- for (k=0; k<8; k++)
- {
- success = TRUE;
- found = FALSE;
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.event_mask = gtk_widget_get_events (widget) |
+ GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
- for (i=0;i<3;i++)
- {
- success = success &&
- GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
- found = found ||
- ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
- }
-
- if (success && found)
- {
- gtk_signal_emit (GTK_OBJECT (ttt),
- tictactoe_signals[TICTACTOE_SIGNAL]);
- break;
- }
- }
-}
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+ widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
-/* example-end */
-</verb></tscreen>
+ widget->style = gtk_style_attach (widget->style, widget->window);
-<!-- ----------------------------------------------------------------- -->
-<sect2>ttt_test.c
-<p>
-<tscreen><verb>
-/* example-start tictactoe ttt_test.c */
+ gdk_window_set_user_data (widget->window, widget);
-#include <gtk/gtk.h>
-#include "tictactoe.h"
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
+}
-void
-win (GtkWidget *widget, gpointer data)
+static void
+gtk_dial_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
{
- g_print ("Yay!\n");
- tictactoe_clear (TICTACTOE (widget));
+ requisition->width = DIAL_DEFAULT_SIZE;
+ requisition->height = DIAL_DEFAULT_SIZE;
}
-int
-main (int argc, char *argv[])
+static void
+gtk_dial_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
{
- GtkWidget *window;
- GtkWidget *ttt;
-
- gtk_init (&argc, &argv);
+ GtkDial *dial;
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-
- gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
-
- gtk_signal_connect (GTK_OBJECT (window), "destroy",
- GTK_SIGNAL_FUNC (gtk_exit), NULL);
-
- gtk_container_set_border_width (GTK_CONTAINER (window), 10);
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_DIAL (widget));
+ g_return_if_fail (allocation != NULL);
- ttt = tictactoe_new ();
-
- gtk_container_add (GTK_CONTAINER (window), ttt);
- gtk_widget_show (ttt);
+ widget->allocation = *allocation;
+ dial = GTK_DIAL (widget);
- gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
- GTK_SIGNAL_FUNC (win), NULL);
+ if (GTK_WIDGET_REALIZED (widget))
+ {
- gtk_widget_show (window);
-
- gtk_main ();
-
- return 0;
+ gdk_window_move_resize (widget->window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
+ }
+ dial->radius = MIN(allocation->width,allocation->height) * 0.45;
+ dial->pointer_width = dial->radius / 5;
}
-/* example-end */
-</verb></tscreen>
+static gint
+gtk_dial_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkDial *dial;
+ GdkPoint points[3];
+ gdouble s,c;
+ gdouble theta;
+ gint xc, yc;
+ gint tick_length;
+ gint i;
-<!-- ----------------------------------------------------------------- -->
-<sect1> GtkDial
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
-<!-- ----------------------------------------------------------------- -->
-<sect2> gtkdial.h
-<p>
-<tscreen><verb>
-/* example-start gtkdial gtkdial.h */
+ if (event->count > 0)
+ return FALSE;
+
+ dial = GTK_DIAL (widget);
-/* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-#ifndef __GTK_DIAL_H__
-#define __GTK_DIAL_H__
+ gdk_window_clear_area (widget->window,
+ 0, 0,
+ widget->allocation.width,
+ widget->allocation.height);
+
+ xc = widget->allocation.width/2;
+ yc = widget->allocation.height/2;
+ /* Draw ticks */
-#include <gdk/gdk.h>
-#include <gtk/gtkadjustment.h>
-#include <gtk/gtkwidget.h>
+ for (i=0; i<25; i++)
+ {
+ theta = (i*M_PI/18. - M_PI/6.);
+ s = sin(theta);
+ c = cos(theta);
+ tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
+
+ gdk_draw_line (widget->window,
+ widget->style->fg_gc[widget->state],
+ xc + c*(dial->radius - tick_length),
+ yc - s*(dial->radius - tick_length),
+ xc + c*dial->radius,
+ yc - s*dial->radius);
+ }
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
+ /* Draw pointer */
+ s = sin(dial->angle);
+ c = cos(dial->angle);
-#define GTK_DIAL(obj) GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
-#define GTK_DIAL_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
-#define GTK_IS_DIAL(obj) GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
+ points[0].x = xc + s*dial->pointer_width/2;
+ points[0].y = yc + c*dial->pointer_width/2;
+ points[1].x = xc + c*dial->radius;
+ points[1].y = yc - s*dial->radius;
+ points[2].x = xc - s*dial->pointer_width/2;
+ points[2].y = yc - c*dial->pointer_width/2;
-typedef struct _GtkDial GtkDial;
-typedef struct _GtkDialClass GtkDialClass;
+ gtk_draw_polygon (widget->style,
+ widget->window,
+ GTK_STATE_NORMAL,
+ GTK_SHADOW_OUT,
+ points, 3,
+ TRUE);
+
+ return FALSE;
+}
-struct _GtkDial
+static gint
+gtk_dial_button_press (GtkWidget *widget,
+ GdkEventButton *event)
{
- GtkWidget widget;
-
- /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
- guint policy : 2;
+ GtkDial *dial;
+ gint dx, dy;
+ double s, c;
+ double d_parallel;
+ double d_perpendicular;
- /* Button currently pressed or 0 if none */
- guint8 button;
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
- /* Dimensions of dial components */
- gint radius;
- gint pointer_width;
+ dial = GTK_DIAL (widget);
- /* ID of update timer, or 0 if none */
- guint32 timer;
+ /* Determine if button press was within pointer region - we
+ do this by computing the parallel and perpendicular distance of
+ the point where the mouse was pressed from the line passing through
+ the pointer */
+
+ dx = event->x - widget->allocation.width / 2;
+ dy = widget->allocation.height / 2 - event->y;
+
+ s = sin(dial->angle);
+ c = cos(dial->angle);
+
+ d_parallel = s*dy + c*dx;
+ d_perpendicular = fabs(s*dx - c*dy);
+
+ if (!dial->button &&
+ (d_perpendicular < dial->pointer_width/2) &&
+ (d_parallel > - dial->pointer_width))
+ {
+ gtk_grab_add (widget);
- /* Current angle */
- gfloat angle;
+ dial->button = event->button;
- /* Old values from adjustment stored so we know when something changes */
- gfloat old_value;
- gfloat old_lower;
- gfloat old_upper;
+ gtk_dial_update_mouse (dial, event->x, event->y);
+ }
- /* The adjustment object that stores the data for this dial */
- GtkAdjustment *adjustment;
-};
+ return FALSE;
+}
-struct _GtkDialClass
+static gint
+gtk_dial_button_release (GtkWidget *widget,
+ GdkEventButton *event)
{
- GtkWidgetClass parent_class;
-};
+ GtkDial *dial;
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
-GtkWidget* gtk_dial_new (GtkAdjustment *adjustment);
-guint gtk_dial_get_type (void);
-GtkAdjustment* gtk_dial_get_adjustment (GtkDial *dial);
-void gtk_dial_set_update_policy (GtkDial *dial,
- GtkUpdateType policy);
+ dial = GTK_DIAL (widget);
-void gtk_dial_set_adjustment (GtkDial *dial,
- GtkAdjustment *adjustment);
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+ if (dial->button == event->button)
+ {
+ gtk_grab_remove (widget);
+ dial->button = 0;
-#endif /* __GTK_DIAL_H__ */
-/* example-end */
-</verb></tscreen>
+ if (dial->policy == GTK_UPDATE_DELAYED)
+ gtk_timeout_remove (dial->timer);
+
+ if ((dial->policy != GTK_UPDATE_CONTINUOUS) &&
+ (dial->old_value != dial->adjustment->value))
+ gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
+ }
-<!-- ----------------------------------------------------------------- -->
-<sect2> gtkdial.c
-<p>
-<tscreen><verb>
-/* example-start gtkdial gtkdial.c */
+ return FALSE;
+}
-/* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-#include <math.h>
-#include <stdio.h>
-#include <gtk/gtkmain.h>
-#include <gtk/gtksignal.h>
+static gint
+gtk_dial_motion_notify (GtkWidget *widget,
+ GdkEventMotion *event)
+{
+ GtkDial *dial;
+ GdkModifierType mods;
+ gint x, y, mask;
-#include "gtkdial.h"
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
-#define SCROLL_DELAY_LENGTH 300
-#define DIAL_DEFAULT_SIZE 100
+ dial = GTK_DIAL (widget);
-/* Forward declarations */
+ if (dial->button != 0)
+ {
+ x = event->x;
+ y = event->y;
-static void gtk_dial_class_init (GtkDialClass *klass);
-static void gtk_dial_init (GtkDial *dial);
-static void gtk_dial_destroy (GtkObject *object);
-static void gtk_dial_realize (GtkWidget *widget);
-static void gtk_dial_size_request (GtkWidget *widget,
- GtkRequisition *requisition);
-static void gtk_dial_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation);
-static gint gtk_dial_expose (GtkWidget *widget,
- GdkEventExpose *event);
-static gint gtk_dial_button_press (GtkWidget *widget,
- GdkEventButton *event);
-static gint gtk_dial_button_release (GtkWidget *widget,
- GdkEventButton *event);
-static gint gtk_dial_motion_notify (GtkWidget *widget,
- GdkEventMotion *event);
-static gint gtk_dial_timer (GtkDial *dial);
+ if (event->is_hint || (event->window != widget->window))
+ gdk_window_get_pointer (widget->window, &x, &y, &mods);
-static void gtk_dial_update_mouse (GtkDial *dial, gint x, gint y);
-static void gtk_dial_update (GtkDial *dial);
-static void gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
- gpointer data);
-static void gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
- gpointer data);
+ switch (dial->button)
+ {
+ case 1:
+ mask = GDK_BUTTON1_MASK;
+ break;
+ case 2:
+ mask = GDK_BUTTON2_MASK;
+ break;
+ case 3:
+ mask = GDK_BUTTON3_MASK;
+ break;
+ default:
+ mask = 0;
+ break;
+ }
-/* Local data */
+ if (mods & mask)
+ gtk_dial_update_mouse (dial, x,y);
+ }
-static GtkWidgetClass *parent_class = NULL;
+ return FALSE;
+}
-guint
-gtk_dial_get_type ()
+static gint
+gtk_dial_timer (GtkDial *dial)
{
- static guint dial_type = 0;
-
- if (!dial_type)
- {
- GtkTypeInfo dial_info =
- {
- "GtkDial",
- sizeof (GtkDial),
- sizeof (GtkDialClass),
- (GtkClassInitFunc) gtk_dial_class_init,
- (GtkObjectInitFunc) gtk_dial_init,
- (GtkArgSetFunc) NULL,
- (GtkArgGetFunc) NULL,
- };
+ g_return_val_if_fail (dial != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
- dial_type = gtk_type_unique (gtk_widget_get_type (), &dial_info);
- }
+ if (dial->policy == GTK_UPDATE_DELAYED)
+ gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
- return dial_type;
+ return FALSE;
}
static void
-gtk_dial_class_init (GtkDialClass *class)
+gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
{
- GtkObjectClass *object_class;
- GtkWidgetClass *widget_class;
+ gint xc, yc;
+ gfloat old_value;
- object_class = (GtkObjectClass*) class;
- widget_class = (GtkWidgetClass*) class;
+ g_return_if_fail (dial != NULL);
+ g_return_if_fail (GTK_IS_DIAL (dial));
- parent_class = gtk_type_class (gtk_widget_get_type ());
+ xc = GTK_WIDGET(dial)->allocation.width / 2;
+ yc = GTK_WIDGET(dial)->allocation.height / 2;
- object_class->destroy = gtk_dial_destroy;
+ old_value = dial->adjustment->value;
+ dial->angle = atan2(yc-y, x-xc);
- widget_class->realize = gtk_dial_realize;
- widget_class->expose_event = gtk_dial_expose;
- widget_class->size_request = gtk_dial_size_request;
- widget_class->size_allocate = gtk_dial_size_allocate;
- widget_class->button_press_event = gtk_dial_button_press;
- widget_class->button_release_event = gtk_dial_button_release;
- widget_class->motion_notify_event = gtk_dial_motion_notify;
-}
+ if (dial->angle < -M_PI/2.)
+ dial->angle += 2*M_PI;
-static void
-gtk_dial_init (GtkDial *dial)
-{
- dial->button = 0;
- dial->policy = GTK_UPDATE_CONTINUOUS;
- dial->timer = 0;
- dial->radius = 0;
- dial->pointer_width = 0;
- dial->angle = 0.0;
- dial->old_value = 0.0;
- dial->old_lower = 0.0;
- dial->old_upper = 0.0;
- dial->adjustment = NULL;
-}
+ if (dial->angle < -M_PI/6)
+ dial->angle = -M_PI/6;
-GtkWidget*
-gtk_dial_new (GtkAdjustment *adjustment)
-{
- GtkDial *dial;
+ if (dial->angle > 7.*M_PI/6.)
+ dial->angle = 7.*M_PI/6.;
- dial = gtk_type_new (gtk_dial_get_type ());
+ dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
+ (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
- if (!adjustment)
- adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+ if (dial->adjustment->value != old_value)
+ {
+ if (dial->policy == GTK_UPDATE_CONTINUOUS)
+ {
+ gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
+ }
+ else
+ {
+ gtk_widget_draw (GTK_WIDGET(dial), NULL);
- gtk_dial_set_adjustment (dial, adjustment);
+ if (dial->policy == GTK_UPDATE_DELAYED)
+ {
+ if (dial->timer)
+ gtk_timeout_remove (dial->timer);
- return GTK_WIDGET (dial);
+ dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
+ (GtkFunction) gtk_dial_timer,
+ (gpointer) dial);
+ }
+ }
+ }
}
static void
-gtk_dial_destroy (GtkObject *object)
+gtk_dial_update (GtkDial *dial)
{
- GtkDial *dial;
-
- g_return_if_fail (object != NULL);
- g_return_if_fail (GTK_IS_DIAL (object));
+ gfloat new_value;
+
+ g_return_if_fail (dial != NULL);
+ g_return_if_fail (GTK_IS_DIAL (dial));
- dial = GTK_DIAL (object);
+ new_value = dial->adjustment->value;
+
+ if (new_value < dial->adjustment->lower)
+ new_value = dial->adjustment->lower;
- if (dial->adjustment)
- gtk_object_unref (GTK_OBJECT (dial->adjustment));
+ if (new_value > dial->adjustment->upper)
+ new_value = dial->adjustment->upper;
- if (GTK_OBJECT_CLASS (parent_class)->destroy)
- (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
-}
+ if (new_value != dial->adjustment->value)
+ {
+ dial->adjustment->value = new_value;
+ gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
+ }
-GtkAdjustment*
-gtk_dial_get_adjustment (GtkDial *dial)
-{
- g_return_val_if_fail (dial != NULL, NULL);
- g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
+ dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
+ (dial->adjustment->upper - dial->adjustment->lower);
- return dial->adjustment;
+ gtk_widget_draw (GTK_WIDGET(dial), NULL);
}
-void
-gtk_dial_set_update_policy (GtkDial *dial,
- GtkUpdateType policy)
+static void
+gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
+ gpointer data)
{
- g_return_if_fail (dial != NULL);
- g_return_if_fail (GTK_IS_DIAL (dial));
+ GtkDial *dial;
- dial->policy = policy;
-}
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (data != NULL);
-void
-gtk_dial_set_adjustment (GtkDial *dial,
- GtkAdjustment *adjustment)
-{
- g_return_if_fail (dial != NULL);
- g_return_if_fail (GTK_IS_DIAL (dial));
+ dial = GTK_DIAL (data);
- if (dial->adjustment)
+ if ((dial->old_value != adjustment->value) ||
+ (dial->old_lower != adjustment->lower) ||
+ (dial->old_upper != adjustment->upper))
{
- gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
- gtk_object_unref (GTK_OBJECT (dial->adjustment));
- }
-
- dial->adjustment = adjustment;
- gtk_object_ref (GTK_OBJECT (dial->adjustment));
-
- gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
- (GtkSignalFunc) gtk_dial_adjustment_changed,
- (gpointer) dial);
- gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
- (GtkSignalFunc) gtk_dial_adjustment_value_changed,
- (gpointer) dial);
-
- dial->old_value = adjustment->value;
- dial->old_lower = adjustment->lower;
- dial->old_upper = adjustment->upper;
+ gtk_dial_update (dial);
- gtk_dial_update (dial);
+ dial->old_value = adjustment->value;
+ dial->old_lower = adjustment->lower;
+ dial->old_upper = adjustment->upper;
+ }
}
static void
-gtk_dial_realize (GtkWidget *widget)
+gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
+ gpointer data)
{
GtkDial *dial;
- GdkWindowAttr attributes;
- gint attributes_mask;
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_DIAL (widget));
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (data != NULL);
- GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
- dial = GTK_DIAL (widget);
+ dial = GTK_DIAL (data);
- attributes.x = widget->allocation.x;
- attributes.y = widget->allocation.y;
- attributes.width = widget->allocation.width;
- attributes.height = widget->allocation.height;
- attributes.wclass = GDK_INPUT_OUTPUT;
- attributes.window_type = GDK_WINDOW_CHILD;
- attributes.event_mask = gtk_widget_get_events (widget) |
- GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
- GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
- GDK_POINTER_MOTION_HINT_MASK;
- attributes.visual = gtk_widget_get_visual (widget);
- attributes.colormap = gtk_widget_get_colormap (widget);
+ if (dial->old_value != adjustment->value)
+ {
+ gtk_dial_update (dial);
- attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
- widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+ dial->old_value = adjustment->value;
+ }
+}
+/* example-end */
+</verb></tscreen>
- widget->style = gtk_style_attach (widget->style, widget->window);
+<!-- ----------------------------------------------------------------- -->
+<sect1> Scribble
+<p>
+<tscreen><verb>
+/* example-start scribble-simple scribble-simple.c */
- gdk_window_set_user_data (widget->window, widget);
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
- gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
+#include <gtk/gtk.h>
+
+/* Backing pixmap for drawing area */
+static GdkPixmap *pixmap = NULL;
+
+/* Create a new backing pixmap of the appropriate size */
+static gint
+configure_event (GtkWidget *widget, GdkEventConfigure *event)
+{
+ if (pixmap)
+ gdk_pixmap_unref(pixmap);
+
+ pixmap = gdk_pixmap_new(widget->window,
+ widget->allocation.width,
+ widget->allocation.height,
+ -1);
+ gdk_draw_rectangle (pixmap,
+ widget->style->white_gc,
+ TRUE,
+ 0, 0,
+ widget->allocation.width,
+ widget->allocation.height);
+
+ return TRUE;
}
-static void
-gtk_dial_size_request (GtkWidget *widget,
- GtkRequisition *requisition)
+/* Redraw the screen from the backing pixmap */
+static gint
+expose_event (GtkWidget *widget, GdkEventExpose *event)
{
- requisition->width = DIAL_DEFAULT_SIZE;
- requisition->height = DIAL_DEFAULT_SIZE;
+ gdk_draw_pixmap(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ pixmap,
+ event->area.x, event->area.y,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+
+ return FALSE;
}
+/* Draw a rectangle on the screen */
static void
-gtk_dial_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
+draw_brush (GtkWidget *widget, gdouble x, gdouble y)
{
- GtkDial *dial;
+ GdkRectangle update_rect;
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_DIAL (widget));
- g_return_if_fail (allocation != NULL);
+ update_rect.x = x - 5;
+ update_rect.y = y - 5;
+ update_rect.width = 10;
+ update_rect.height = 10;
+ gdk_draw_rectangle (pixmap,
+ widget->style->black_gc,
+ TRUE,
+ update_rect.x, update_rect.y,
+ update_rect.width, update_rect.height);
+ gtk_widget_draw (widget, &update_rect);
+}
- widget->allocation = *allocation;
- dial = GTK_DIAL (widget);
+static gint
+button_press_event (GtkWidget *widget, GdkEventButton *event)
+{
+ if (event->button == 1 && pixmap != NULL)
+ draw_brush (widget, event->x, event->y);
- if (GTK_WIDGET_REALIZED (widget))
- {
+ return TRUE;
+}
- gdk_window_move_resize (widget->window,
- allocation->x, allocation->y,
- allocation->width, allocation->height);
+static gint
+motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
+{
+ int x, y;
+ GdkModifierType state;
+ if (event->is_hint)
+ gdk_window_get_pointer (event->window, &x, &y, &state);
+ else
+ {
+ x = event->x;
+ y = event->y;
+ state = event->state;
}
- dial->radius = MIN(allocation->width,allocation->height) * 0.45;
- dial->pointer_width = dial->radius / 5;
+
+ if (state & GDK_BUTTON1_MASK && pixmap != NULL)
+ draw_brush (widget, x, y);
+
+ return TRUE;
}
-static gint
-gtk_dial_expose (GtkWidget *widget,
- GdkEventExpose *event)
+void
+quit ()
{
- GtkDial *dial;
- GdkPoint points[3];
- gdouble s,c;
- gdouble theta;
- gint xc, yc;
- gint tick_length;
- gint i;
+ gtk_exit (0);
+}
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *window;
+ GtkWidget *drawing_area;
+ GtkWidget *vbox;
- if (event->count > 0)
- return FALSE;
-
- dial = GTK_DIAL (widget);
+ GtkWidget *button;
- gdk_window_clear_area (widget->window,
- 0, 0,
- widget->allocation.width,
- widget->allocation.height);
+ gtk_init (&argc, &argv);
- xc = widget->allocation.width/2;
- yc = widget->allocation.height/2;
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_widget_set_name (window, "Test Input");
- /* Draw ticks */
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), vbox);
+ gtk_widget_show (vbox);
- for (i=0; i<25; i++)
- {
- theta = (i*M_PI/18. - M_PI/6.);
- s = sin(theta);
- c = cos(theta);
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ GTK_SIGNAL_FUNC (quit), NULL);
- tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
-
- gdk_draw_line (widget->window,
- widget->style->fg_gc[widget->state],
- xc + c*(dial->radius - tick_length),
- yc - s*(dial->radius - tick_length),
- xc + c*dial->radius,
- yc - s*dial->radius);
- }
+ /* Create the drawing area */
- /* Draw pointer */
+ drawing_area = gtk_drawing_area_new ();
+ gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
+ gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
- s = sin(dial->angle);
- c = cos(dial->angle);
+ gtk_widget_show (drawing_area);
+ /* Signals used to handle backing pixmap */
- points[0].x = xc + s*dial->pointer_width/2;
- points[0].y = yc + c*dial->pointer_width/2;
- points[1].x = xc + c*dial->radius;
- points[1].y = yc - s*dial->radius;
- points[2].x = xc - s*dial->pointer_width/2;
- points[2].y = yc - c*dial->pointer_width/2;
+ gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
+ (GtkSignalFunc) expose_event, NULL);
+ gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
+ (GtkSignalFunc) configure_event, NULL);
- gtk_draw_polygon (widget->style,
- widget->window,
- GTK_STATE_NORMAL,
- GTK_SHADOW_OUT,
- points, 3,
- TRUE);
-
- return FALSE;
-}
+ /* Event signals */
-static gint
-gtk_dial_button_press (GtkWidget *widget,
- GdkEventButton *event)
-{
- GtkDial *dial;
- gint dx, dy;
- double s, c;
- double d_parallel;
- double d_perpendicular;
+ gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
+ (GtkSignalFunc) motion_notify_event, NULL);
+ gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
+ (GtkSignalFunc) button_press_event, NULL);
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
+ gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
+ | GDK_LEAVE_NOTIFY_MASK
+ | GDK_BUTTON_PRESS_MASK
+ | GDK_POINTER_MOTION_MASK
+ | GDK_POINTER_MOTION_HINT_MASK);
- dial = GTK_DIAL (widget);
+ /* .. And a quit button */
+ button = gtk_button_new_with_label ("Quit");
+ gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
- /* Determine if button press was within pointer region - we
- do this by computing the parallel and perpendicular distance of
- the point where the mouse was pressed from the line passing through
- the pointer */
-
- dx = event->x - widget->allocation.width / 2;
- dy = widget->allocation.height / 2 - event->y;
-
- s = sin(dial->angle);
- c = cos(dial->angle);
-
- d_parallel = s*dy + c*dx;
- d_perpendicular = fabs(s*dx - c*dy);
-
- if (!dial->button &&
- (d_perpendicular < dial->pointer_width/2) &&
- (d_parallel > - dial->pointer_width))
- {
- gtk_grab_add (widget);
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (gtk_widget_destroy),
+ GTK_OBJECT (window));
+ gtk_widget_show (button);
- dial->button = event->button;
+ gtk_widget_show (window);
- gtk_dial_update_mouse (dial, event->x, event->y);
- }
+ gtk_main ();
- return FALSE;
+ return 0;
}
+/* example-end */
+</verb></tscreen>
-static gint
-gtk_dial_button_release (GtkWidget *widget,
- GdkEventButton *event)
+<!-- ***************************************************************** -->
+<sect> List Widget
+<!-- ***************************************************************** -->
+<p>
+NOTE: The GtkList widget has been superseded by the GtkCList
+widget. It is detailed here just for completeness.
+
+The GtkList widget is designed to act as a vertical container for
+widgets that should be of the type GtkListItem.
+
+A GtkList widget has its own window to receive events and its own
+background color which is usually white. As it is directly derived
+from a GtkContainer it can be treated as such by using the
+GTK_CONTAINER(List) macro, see the GtkContainer widget for more on
+this. One should already be familiar with the usage of a GList and
+its related functions g_list_*() to be able to use the GtkList widget
+to it full extent.
+
+There is one field inside the structure definition of the GtkList
+widget that will be of greater interest to us, this is:
+
+<tscreen><verb>
+struct _GtkList
{
- GtkDial *dial;
+ ...
+ GList *selection;
+ guint selection_mode;
+ ...
+};
+</verb></tscreen>
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
+The selection field of a GtkList points to a linked list of all items
+that are currently selected, or NULL if the selection is empty. So to
+learn about the current selection we read the GTK_LIST()->selection
+field, but do not modify it since the internal fields are maintained
+by the gtk_list_*() functions.
- dial = GTK_DIAL (widget);
+The selection_mode of the GtkList determines the selection facilities
+of a GtkList and therefore the contents of the GTK_LIST()->selection
+field. The selection_mode may be one of the following:
- if (dial->button == event->button)
- {
- gtk_grab_remove (widget);
+<itemize>
+<item> GTK_SELECTION_SINGLE - The selection is either NULL
+ or contains a GList pointer
+ for a single selected item.
- dial->button = 0;
+<item> GTK_SELECTION_BROWSE - The selection is NULL if the list
+ contains no widgets or insensitive
+ ones only, otherwise it contains
+ a GList pointer for one GList
+ structure, and therefore exactly
+ one list item.
- if (dial->policy == GTK_UPDATE_DELAYED)
- gtk_timeout_remove (dial->timer);
-
- if ((dial->policy != GTK_UPDATE_CONTINUOUS) &&
- (dial->old_value != dial->adjustment->value))
- gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
- }
+<item> GTK_SELECTION_MULTIPLE - The selection is NULL if no list
+ items are selected or a GList pointer
+ for the first selected item. That
+ in turn points to a GList structure
+ for the second selected item and so
+ on.
- return FALSE;
-}
+<item> GTK_SELECTION_EXTENDED - The selection is always NULL.
+</itemize>
-static gint
-gtk_dial_motion_notify (GtkWidget *widget,
- GdkEventMotion *event)
-{
- GtkDial *dial;
- GdkModifierType mods;
- gint x, y, mask;
+The default is GTK_SELECTION_MULTIPLE.
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
+<!-- ----------------------------------------------------------------- -->
+<sect1> Signals
+<p>
+<tscreen><verb>
+void selection_changed( GtkList *list );
+</verb></tscreen>
- dial = GTK_DIAL (widget);
+This signal will be invoked whenever the selection field of a GtkList
+has changed. This happens when a child of the GtkList got selected or
+deselected.
- if (dial->button != 0)
- {
- x = event->x;
- y = event->y;
+<tscreen><verb>
+void select_child( GtkList *list,
+ GtkWidget *child);
+</verb></tscreen>
- if (event->is_hint || (event->window != widget->window))
- gdk_window_get_pointer (widget->window, &x, &y, &mods);
+This signal is invoked when a child of the GtkList is about to get
+selected. This happens mainly on calls to gtk_list_select_item(),
+gtk_list_select_child(), button presses and sometimes indirectly
+triggered on some else occasions where children get added to or
+removed from the GtkList.
- switch (dial->button)
- {
- case 1:
- mask = GDK_BUTTON1_MASK;
- break;
- case 2:
- mask = GDK_BUTTON2_MASK;
- break;
- case 3:
- mask = GDK_BUTTON3_MASK;
- break;
- default:
- mask = 0;
- break;
- }
+<tscreen><verb>
+void unselect_child( GtkList *list,
+ GtkWidget *child );
+</verb></tscreen>
- if (mods & mask)
- gtk_dial_update_mouse (dial, x,y);
- }
+This signal is invoked when a child of the GtkList is about to get
+deselected. This happens mainly on calls to gtk_list_unselect_item(),
+gtk_list_unselect_child(), button presses and sometimes indirectly
+triggered on some else occasions where children get added to or
+removed from the GtkList.
- return FALSE;
-}
+<!-- ----------------------------------------------------------------- -->
+<sect1> Functions
+<p>
+<tscreen><verb>
+guint gtk_list_get_type( void );
+</verb></tscreen>
-static gint
-gtk_dial_timer (GtkDial *dial)
-{
- g_return_val_if_fail (dial != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
+Returns the `GtkList' type identifier.
- if (dial->policy == GTK_UPDATE_DELAYED)
- gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
+<tscreen><verb>
+GtkWidget *gtk_list_new( void );
+</verb></tscreen>
- return FALSE;
-}
+Create a new GtkList object. The new widget is returned as a pointer
+to a GtkWidget object. NULL is returned on failure.
-static void
-gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
-{
- gint xc, yc;
- gfloat old_value;
+<tscreen><verb>
+void gtk_list_insert_items( GtkList *list,
+ GList *items,
+ gint position );
+</verb></tscreen>
- g_return_if_fail (dial != NULL);
- g_return_if_fail (GTK_IS_DIAL (dial));
+Insert list items into the list, starting at <tt/position/.
+<tt/items/ is a doubly linked list where each nodes data pointer is
+expected to point to a newly created GtkListItem. The GList nodes of
+<tt/items/ are taken over by the list.
- xc = GTK_WIDGET(dial)->allocation.width / 2;
- yc = GTK_WIDGET(dial)->allocation.height / 2;
+<tscreen><verb>
+void gtk_list_append_items( GtkList *list,
+ GList *items);
+</verb></tscreen>
- old_value = dial->adjustment->value;
- dial->angle = atan2(yc-y, x-xc);
+Insert list items just like gtk_list_insert_items() at the end of the
+list. The GList nodes of <tt/items/ are taken over by the list.
- if (dial->angle < -M_PI/2.)
- dial->angle += 2*M_PI;
+<tscreen><verb>
+void gtk_list_prepend_items( GtkList *list,
+ GList *items);
+</verb></tscreen>
- if (dial->angle < -M_PI/6)
- dial->angle = -M_PI/6;
+Insert list items just like gtk_list_insert_items() at the very
+beginning of the list. The GList nodes of <tt/items/ are taken over by
+the list.
- if (dial->angle > 7.*M_PI/6.)
- dial->angle = 7.*M_PI/6.;
+<tscreen><verb>
+void gtk_list_remove_items( GtkList *list,
+ GList *items);
+</verb></tscreen>
- dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
- (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
+Remove list items from the list. <tt/items/ is a doubly linked list
+where each nodes data pointer is expected to point to a direct child
+of list. It is the callers responsibility to make a call to
+g_list_free(items) afterwards. Also the caller has to destroy the list
+items himself.
- if (dial->adjustment->value != old_value)
- {
- if (dial->policy == GTK_UPDATE_CONTINUOUS)
- {
- gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
- }
- else
- {
- gtk_widget_draw (GTK_WIDGET(dial), NULL);
+<tscreen><verb>
+void gtk_list_clear_items( GtkList *list,
+ gint start,
+ gint end );
+</verb></tscreen>
- if (dial->policy == GTK_UPDATE_DELAYED)
- {
- if (dial->timer)
- gtk_timeout_remove (dial->timer);
+Remove and destroy list items from the list. A widget is affected if
+its current position within the list is in the range specified by
+<tt/start/ and <tt/end/.
- dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
- (GtkFunction) gtk_dial_timer,
- (gpointer) dial);
- }
- }
- }
-}
+<tscreen><verb>
+void gtk_list_select_item( GtkList *list,
+ gint item );
+</verb></tscreen>
-static void
-gtk_dial_update (GtkDial *dial)
-{
- gfloat new_value;
-
- g_return_if_fail (dial != NULL);
- g_return_if_fail (GTK_IS_DIAL (dial));
+Invoke the select_child signal for a list item specified through its
+current position within the list.
- new_value = dial->adjustment->value;
-
- if (new_value < dial->adjustment->lower)
- new_value = dial->adjustment->lower;
+<tscreen><verb>
+void gtk_list_unselect_item( GtkList *list,
+ gint item);
+</verb></tscreen>
- if (new_value > dial->adjustment->upper)
- new_value = dial->adjustment->upper;
+Invoke the unselect_child signal for a list item specified through its
+current position within the list.
- if (new_value != dial->adjustment->value)
- {
- dial->adjustment->value = new_value;
- gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
- }
+<tscreen><verb>
+void gtk_list_select_child( GtkList *list,
+ GtkWidget *child);
+</verb></tscreen>
- dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
- (dial->adjustment->upper - dial->adjustment->lower);
+Invoke the select_child signal for the specified child.
- gtk_widget_draw (GTK_WIDGET(dial), NULL);
-}
+<tscreen><verb>
+void gtk_list_unselect_child( GtkList *list,
+ GtkWidget *child);
+</verb></tscreen>
-static void
-gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
- gpointer data)
-{
- GtkDial *dial;
+Invoke the unselect_child signal for the specified child.
- g_return_if_fail (adjustment != NULL);
- g_return_if_fail (data != NULL);
+<tscreen><verb>
+gint gtk_list_child_position( GtkList *list,
+ GtkWidget *child);
+</verb></tscreen>
- dial = GTK_DIAL (data);
+Return the position of <tt/child/ within the list. "-1" is returned on
+failure.
- if ((dial->old_value != adjustment->value) ||
- (dial->old_lower != adjustment->lower) ||
- (dial->old_upper != adjustment->upper))
- {
- gtk_dial_update (dial);
+<tscreen><verb>
+void gtk_list_set_selection_mode( GtkList *list,
+ GtkSelectionMode mode );
+</verb></tscreen>
- dial->old_value = adjustment->value;
- dial->old_lower = adjustment->lower;
- dial->old_upper = adjustment->upper;
- }
-}
+Set the selection mode MODE which can be of GTK_SELECTION_SINGLE,
+GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE or
+GTK_SELECTION_EXTENDED.
-static void
-gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
- gpointer data)
-{
- GtkDial *dial;
+<tscreen><verb>
+GtkList *GTK_LIST( gpointer obj );
+</verb></tscreen>
- g_return_if_fail (adjustment != NULL);
- g_return_if_fail (data != NULL);
+Cast a generic pointer to `GtkList *'. *Note Standard Macros::, for
+more info.
- dial = GTK_DIAL (data);
+<tscreen><verb>
+GtkListClass *GTK_LIST_CLASS( gpointer class);
+</verb></tscreen>
- if (dial->old_value != adjustment->value)
- {
- gtk_dial_update (dial);
+Cast a generic pointer to `GtkListClass*'. *Note Standard Macros::,
+for more info.
- dial->old_value = adjustment->value;
- }
-}
-/* example-end */
+<tscreen><verb>
+gint GTK_IS_LIST( gpointer obj);
</verb></tscreen>
+Determine if a generic pointer refers to a `GtkList' object. *Note
+Standard Macros::, for more info.
+
<!-- ----------------------------------------------------------------- -->
-<sect1> Scribble
+<sect1> Example
<p>
+Following is an example program that will print out the changes of the
+selection of a GtkList, and lets you "arrest" list items into a prison
+by selecting them with the rightmost mouse button.
+
<tscreen><verb>
-/* example-start scribble-simple scribble-simple.c */
+/* example-start list list.c */
-/* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+/* Include the gtk+ header files
+ * Include stdio.h, we need that for the printf() function
*/
+#include <gtk/gtk.h>
+#include <stdio.h>
-#include <gtk/gtk.h>
-
-/* Backing pixmap for drawing area */
-static GdkPixmap *pixmap = NULL;
+/* This is our data identification string to store
+ * data in list items
+ */
+const gchar *list_item_data_key="list_item_data";
-/* Create a new backing pixmap of the appropriate size */
-static gint
-configure_event (GtkWidget *widget, GdkEventConfigure *event)
-{
- if (pixmap)
- gdk_pixmap_unref(pixmap);
- pixmap = gdk_pixmap_new(widget->window,
- widget->allocation.width,
- widget->allocation.height,
- -1);
- gdk_draw_rectangle (pixmap,
- widget->style->white_gc,
- TRUE,
- 0, 0,
- widget->allocation.width,
- widget->allocation.height);
+/* prototypes for signal handler that we are going to connect
+ * to the GtkList widget
+ */
+static void sigh_print_selection( GtkWidget *gtklist,
+ gpointer func_data);
- return TRUE;
-}
+static void sigh_button_event( GtkWidget *gtklist,
+ GdkEventButton *event,
+ GtkWidget *frame );
-/* Redraw the screen from the backing pixmap */
-static gint
-expose_event (GtkWidget *widget, GdkEventExpose *event)
-{
- gdk_draw_pixmap(widget->window,
- widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
- pixmap,
- event->area.x, event->area.y,
- event->area.x, event->area.y,
- event->area.width, event->area.height);
- return FALSE;
-}
+/* Main function to set up the user interface */
-/* Draw a rectangle on the screen */
-static void
-draw_brush (GtkWidget *widget, gdouble x, gdouble y)
-{
- GdkRectangle update_rect;
+gint main (int argc,
+ gchar *argv[])
+{
+ GtkWidget *separator;
+ GtkWidget *window;
+ GtkWidget *vbox;
+ GtkWidget *scrolled_window;
+ GtkWidget *frame;
+ GtkWidget *gtklist;
+ GtkWidget *button;
+ GtkWidget *list_item;
+ GList *dlist;
+ guint i;
+ gchar buffer[64];
+
+
+ /* Initialize gtk+ (and subsequently gdk) */
- update_rect.x = x - 5;
- update_rect.y = y - 5;
- update_rect.width = 10;
- update_rect.height = 10;
- gdk_draw_rectangle (pixmap,
- widget->style->black_gc,
- TRUE,
- update_rect.x, update_rect.y,
- update_rect.width, update_rect.height);
- gtk_widget_draw (widget, &update_rect);
+ gtk_init(&argc, &argv);
+
+
+ /* Create a window to put all the widgets in
+ * connect gtk_main_quit() to the "destroy" event of
+ * the window to handle window manager close-window-events
+ */
+ window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(window), "GtkList Example");
+ gtk_signal_connect(GTK_OBJECT(window),
+ "destroy",
+ GTK_SIGNAL_FUNC(gtk_main_quit),
+ NULL);
+
+
+ /* Inside the window we need a box to arrange the widgets
+ * vertically */
+ vbox=gtk_vbox_new(FALSE, 5);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
+ gtk_container_add(GTK_CONTAINER(window), vbox);
+ gtk_widget_show(vbox);
+
+ /* This is the scrolled window to put the GtkList widget inside */
+ scrolled_window=gtk_scrolled_window_new(NULL, NULL);
+ gtk_widget_set_usize(scrolled_window, 250, 150);
+ gtk_container_add(GTK_CONTAINER(vbox), scrolled_window);
+ gtk_widget_show(scrolled_window);
+
+ /* Create the GtkList widget.
+ * Connect the sigh_print_selection() signal handler
+ * function to the "selection_changed" signal of the GtkList
+ * to print out the selected items each time the selection
+ * has changed */
+ gtklist=gtk_list_new();
+ gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window),
+ gtklist);
+ gtk_widget_show(gtklist);
+ gtk_signal_connect(GTK_OBJECT(gtklist),
+ "selection_changed",
+ GTK_SIGNAL_FUNC(sigh_print_selection),
+ NULL);
+
+ /* We create a "Prison" to put a list item in ;) */
+ frame=gtk_frame_new("Prison");
+ gtk_widget_set_usize(frame, 200, 50);
+ gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
+ gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
+ gtk_container_add(GTK_CONTAINER(vbox), frame);
+ gtk_widget_show(frame);
+
+ /* Connect the sigh_button_event() signal handler to the GtkList
+ * which will handle the "arresting" of list items
+ */
+ gtk_signal_connect(GTK_OBJECT(gtklist),
+ "button_release_event",
+ GTK_SIGNAL_FUNC(sigh_button_event),
+ frame);
+
+ /* Create a separator */
+ separator=gtk_hseparator_new();
+ gtk_container_add(GTK_CONTAINER(vbox), separator);
+ gtk_widget_show(separator);
+
+ /* Finally create a button and connect it's "clicked" signal
+ * to the destruction of the window */
+ button=gtk_button_new_with_label("Close");
+ gtk_container_add(GTK_CONTAINER(vbox), button);
+ gtk_widget_show(button);
+ gtk_signal_connect_object(GTK_OBJECT(button),
+ "clicked",
+ GTK_SIGNAL_FUNC(gtk_widget_destroy),
+ GTK_OBJECT(window));
+
+
+ /* Now we create 5 list items, each having it's own
+ * label and add them to the GtkList using gtk_container_add()
+ * Also we query the text string from the label and
+ * associate it with the list_item_data_key for each list item
+ */
+ for (i=0; i<5; i++) {
+ GtkWidget *label;
+ gchar *string;
+
+ sprintf(buffer, "ListItemContainer with Label #%d", i);
+ label=gtk_label_new(buffer);
+ list_item=gtk_list_item_new();
+ gtk_container_add(GTK_CONTAINER(list_item), label);
+ gtk_widget_show(label);
+ gtk_container_add(GTK_CONTAINER(gtklist), list_item);
+ gtk_widget_show(list_item);
+ gtk_label_get(GTK_LABEL(label), &string);
+ gtk_object_set_data(GTK_OBJECT(list_item),
+ list_item_data_key,
+ string);
+ }
+ /* Here, we are creating another 5 labels, this time
+ * we use gtk_list_item_new_with_label() for the creation
+ * we can't query the text string from the label because
+ * we don't have the labels pointer and therefore
+ * we just associate the list_item_data_key of each
+ * list item with the same text string.
+ * For adding of the list items we put them all into a doubly
+ * linked list (GList), and then add them by a single call to
+ * gtk_list_append_items().
+ * Because we use g_list_prepend() to put the items into the
+ * doubly linked list, their order will be descending (instead
+ * of ascending when using g_list_append())
+ */
+ dlist=NULL;
+ for (; i<10; i++) {
+ sprintf(buffer, "List Item with Label %d", i);
+ list_item=gtk_list_item_new_with_label(buffer);
+ dlist=g_list_prepend(dlist, list_item);
+ gtk_widget_show(list_item);
+ gtk_object_set_data(GTK_OBJECT(list_item),
+ list_item_data_key,
+ "ListItem with integrated Label");
+ }
+ gtk_list_append_items(GTK_LIST(gtklist), dlist);
+
+ /* Finally we want to see the window, don't we? ;) */
+ gtk_widget_show(window);
+
+ /* Fire up the main event loop of gtk */
+ gtk_main();
+
+ /* We get here after gtk_main_quit() has been called which
+ * happens if the main window gets destroyed
+ */
+ return(0);
}
-static gint
-button_press_event (GtkWidget *widget, GdkEventButton *event)
+/* This is the signal handler that got connected to button
+ * press/release events of the GtkList
+ */
+void sigh_button_event( GtkWidget *gtklist,
+ GdkEventButton *event,
+ GtkWidget *frame )
{
- if (event->button == 1 && pixmap != NULL)
- draw_brush (widget, event->x, event->y);
-
- return TRUE;
+ /* We only do something if the third (rightmost mouse button
+ * was released
+ */
+ if (event->type==GDK_BUTTON_RELEASE &&
+ event->button==3) {
+ GList *dlist, *free_list;
+ GtkWidget *new_prisoner;
+
+ /* Fetch the currently selected list item which
+ * will be our next prisoner ;)
+ */
+ dlist=GTK_LIST(gtklist)->selection;
+ if (dlist)
+ new_prisoner=GTK_WIDGET(dlist->data);
+ else
+ new_prisoner=NULL;
+
+ /* Look for already imprisoned list items, we
+ * will put them back into the list.
+ * Remember to free the doubly linked list that
+ * gtk_container_children() returns
+ */
+ dlist=gtk_container_children(GTK_CONTAINER(frame));
+ free_list=dlist;
+ while (dlist) {
+ GtkWidget *list_item;
+
+ list_item=dlist->data;
+
+ gtk_widget_reparent(list_item, gtklist);
+
+ dlist=dlist->next;
+ }
+ g_list_free(free_list);
+
+ /* If we have a new prisoner, remove him from the
+ * GtkList and put him into the frame "Prison".
+ * We need to unselect the item first.
+ */
+ if (new_prisoner) {
+ GList static_dlist;
+
+ static_dlist.data=new_prisoner;
+ static_dlist.next=NULL;
+ static_dlist.prev=NULL;
+
+ gtk_list_unselect_child(GTK_LIST(gtklist),
+ new_prisoner);
+ gtk_widget_reparent(new_prisoner, frame);
+ }
+ }
}
-static gint
-motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
+/* This is the signal handler that gets called if GtkList
+ * emits the "selection_changed" signal
+ */
+void sigh_print_selection( GtkWidget *gtklist,
+ gpointer func_data)
{
- int x, y;
- GdkModifierType state;
-
- if (event->is_hint)
- gdk_window_get_pointer (event->window, &x, &y, &state);
- else
- {
- x = event->x;
- y = event->y;
- state = event->state;
+ GList *dlist;
+
+ /* Fetch the doubly linked list of selected items
+ * of the GtkList, remember to treat this as read-only!
+ */
+ dlist=GTK_LIST(gtklist)->selection;
+
+ /* If there are no selected items there is nothing more
+ * to do than just telling the user so
+ */
+ if (!dlist) {
+ g_print("Selection cleared\n");
+ return;
}
+ /* Ok, we got a selection and so we print it
+ */
+ g_print("The selection is a ");
- if (state & GDK_BUTTON1_MASK && pixmap != NULL)
- draw_brush (widget, x, y);
-
- return TRUE;
+ /* Get the list item from the doubly linked list
+ * and then query the data associated with list_item_data_key.
+ * We then just print it */
+ while (dlist) {
+ GtkObject *list_item;
+ gchar *item_data_string;
+
+ list_item=GTK_OBJECT(dlist->data);
+ item_data_string=gtk_object_get_data(list_item,
+ list_item_data_key);
+ g_print("%s ", item_data_string);
+
+ dlist=dlist->next;
+ }
+ g_print("\n");
}
+/* example-end */
+</verb></tscreen>
-void
-quit ()
-{
- gtk_exit (0);
-}
+<!-- ----------------------------------------------------------------- -->
+<sect1> List Item Widget
+<p>
+The GtkListItem widget is designed to act as a container holding up to
+one child, providing functions for selection/deselection just like the
+GtkList widget requires them for its children.
-int
-main (int argc, char *argv[])
-{
- GtkWidget *window;
- GtkWidget *drawing_area;
- GtkWidget *vbox;
+A GtkListItem has its own window to receive events and has its own
+background color which is usually white.
- GtkWidget *button;
+As it is directly derived from a GtkItem it can be treated as such by
+using the GTK_ITEM(ListItem) macro, see the GtkItem widget for more on
+this. Usually a GtkListItem just holds a label to identify e.g. a
+filename within a GtkList -- therefore the convenience function
+gtk_list_item_new_with_label() is provided. The same effect can be
+achieved by creating a GtkLabel on its own, setting its alignment to
+xalign=0 and yalign=0.5 with a subsequent container addition to the
+GtkListItem.
- gtk_init (&argc, &argv);
+As one is not forced to add a GtkLabel to a GtkListItem, you could
+also add a GtkVBox or a GtkArrow etc. to the GtkListItem.
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_widget_set_name (window, "Test Input");
+<!-- ----------------------------------------------------------------- -->
+<sect1> Signals
+<p>
+A GtkListItem does not create new signals on its own, but inherits
+the signals of a GtkItem. *Note GtkItem::, for more info.
- vbox = gtk_vbox_new (FALSE, 0);
- gtk_container_add (GTK_CONTAINER (window), vbox);
- gtk_widget_show (vbox);
+<!-- ----------------------------------------------------------------- -->
+<sect1> Functions
+<p>
+<tscreen><verb>
+guint gtk_list_item_get_type( void );
+</verb></tscreen>
- gtk_signal_connect (GTK_OBJECT (window), "destroy",
- GTK_SIGNAL_FUNC (quit), NULL);
+Returns the `GtkListItem' type identifier.
- /* Create the drawing area */
+<tscreen><verb>
+GtkWidget *gtk_list_item_new( void );
+</verb></tscreen>
- drawing_area = gtk_drawing_area_new ();
- gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
- gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
+Create a new GtkListItem object. The new widget is returned as a
+pointer to a GtkWidget object. NULL is returned on failure.
- gtk_widget_show (drawing_area);
+<tscreen><verb>
+GtkWidget *gtk_list_item_new_with_label( gchar *label );
+</verb></tscreen>
- /* Signals used to handle backing pixmap */
+Create a new GtkListItem object, having a single GtkLabel as the sole
+child. The new widget is returned as a pointer to a GtkWidget
+object. NULL is returned on failure.
- gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
- (GtkSignalFunc) expose_event, NULL);
- gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
- (GtkSignalFunc) configure_event, NULL);
+<tscreen><verb>
+void gtk_list_item_select( GtkListItem *list_item );
+</verb></tscreen>
- /* Event signals */
+This function is basically a wrapper around a call to gtk_item_select
+(GTK_ITEM (list_item)) which will emit the select signal. *Note
+GtkItem::, for more info.
- gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
- (GtkSignalFunc) motion_notify_event, NULL);
- gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
- (GtkSignalFunc) button_press_event, NULL);
+<tscreen><verb>
+void gtk_list_item_deselect( GtkListItem *list_item );
+</verb></tscreen>
- gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
- | GDK_LEAVE_NOTIFY_MASK
- | GDK_BUTTON_PRESS_MASK
- | GDK_POINTER_MOTION_MASK
- | GDK_POINTER_MOTION_HINT_MASK);
+This function is basically a wrapper around a call to
+gtk_item_deselect (GTK_ITEM (list_item)) which will emit the deselect
+signal. *Note GtkItem::, for more info.
- /* .. And a quit button */
- button = gtk_button_new_with_label ("Quit");
- gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+<tscreen><verb>
+GtkListItem *GTK_LIST_ITEM( gpointer obj );
+</verb></tscreen>
- gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
- GTK_SIGNAL_FUNC (gtk_widget_destroy),
- GTK_OBJECT (window));
- gtk_widget_show (button);
+Cast a generic pointer to `GtkListItem*'. *Note Standard Macros::, for
+more info.
- gtk_widget_show (window);
+<tscreen><verb>
+GtkListItemClass *GTK_LIST_ITEM_CLASS( gpointer class );
+</verb></tscreen>
- gtk_main ();
+Cast a generic pointer to GtkListItemClass*. *Note Standard Macros::,
+for more info.
- return 0;
-}
-/* example-end */
+<tscreen><verb>
+gint GTK_IS_LIST_ITEM( gpointer obj );
</verb></tscreen>
+Determine if a generic pointer refers to a `GtkListItem' object.
+*Note Standard Macros::, for more info.
+
+<!-- ----------------------------------------------------------------- -->
+<sect1> Example
+<p>
+Please see the GtkList example on this, which covers the usage of a
+GtkListItem as well.
+
+
</article>
name="<gale@gtk.org>"></tt>
Ian Main <tt><htmlurl url="mailto:imain@gtk.org"
name="<imain@gtk.org>"></tt>,
-<date>January 27th, 1999
+<date>January 28th, 1999
<!-- ***************************************************************** -->
<sect>Introduction
<sect> Container Widgets
<!-- ***************************************************************** -->
-<!-- ----------------------------------------------------------------- -->
-<sect1> Notebooks
-<p>
-The NoteBook Widget is a collection of 'pages' that overlap each
-other, each page contains different information. This widget has
-become more common lately in GUI programming, and it is a good way to
-show blocks of similar information that warrant separation in their
-display.
+<!-- ----------------------------------------------------------------- -->
+<sect1>The EventBox <label id="sec_EventBox">
+<p>
+Some GTK widgets don't have associated X windows, so they just draw on
+their parents. Because of this, they cannot receive events and if they
+are incorrectly sized, they don't clip so you can get messy
+overwriting etc. If you require more from these widgets, the EventBox
+is for you.
-The first function call you will need to know, as you can probably
-guess by now, is used to create a new notebook widget.
+At first glance, the EventBox widget might appear to be totally
+useless. It draws nothing on the screen and responds to no
+events. However, it does serve a function - it provides an X window
+for its child widget. This is important as many GTK widgets do not
+have an associated X window. Not having an X window saves memory and
+improves performance, but also has some drawbacks. A widget without an
+X window cannot receive events, and does not perform any clipping on
+its contents. Although the name <em/EventBox/ emphasizes the
+event-handling function, the widget can also be used for clipping.
+(and more, see the example below).
+
+To create a new EventBox widget, use:
<tscreen><verb>
-GtkWidget *gtk_notebook_new( void );
+GtkWidget *gtk_event_box_new( void );
</verb></tscreen>
-Once the notebook has been created, there are a number of functions
-that operate on the notebook widget. Let's look at them individually.
-
-The first one we will look at is how to position the page indicators.
-These page indicators or 'tabs' as they are referred to, can be
-positioned in four ways: top, bottom, left, or right.
+A child widget can then be added to this EventBox:
<tscreen><verb>
-void gtk_notebook_set_tab_pos( GtkNotebook *notebook,
- GtkPositionType pos );
+gtk_container_add( GTK_CONTAINER(event_box), widget );
</verb></tscreen>
-GtkPostionType will be one of the following, and they are pretty self explanatory:
-<itemize>
-<item> GTK_POS_LEFT
-<item> GTK_POS_RIGHT
-<item> GTK_POS_TOP
-<item> GTK_POS_BOTTOM
-</itemize>
-
-GTK_POS_TOP is the default.
-
-Next we will look at how to add pages to the notebook. There are three
-ways to add pages to the NoteBook. Let's look at the first two
-together as they are quite similar.
+The following example demonstrates both uses of an EventBox - a label
+is created that is clipped to a small box, and set up so that a
+mouse-click on the label causes the program to exit. Resizing the
+window reveals varying amounts of the label.
<tscreen><verb>
-void gtk_notebook_append_page( GtkNotebook *notebook,
- GtkWidget *child,
- GtkWidget *tab_label );
+/* example-start eventbox eventbox.c */
-void gtk_notebook_prepend_page( GtkNotebook *notebook,
- GtkWidget *child,
- GtkWidget *tab_label );
+#include <gtk/gtk.h>
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *window;
+ GtkWidget *event_box;
+ GtkWidget *label;
+
+ gtk_init (&argc, &argv);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_window_set_title (GTK_WINDOW (window), "Event Box");
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ GTK_SIGNAL_FUNC (gtk_exit), NULL);
+
+ gtk_container_set_border_width (GTK_CONTAINER (window), 10);
+
+ /* Create an EventBox and add it to our toplevel window */
+
+ event_box = gtk_event_box_new ();
+ gtk_container_add (GTK_CONTAINER(window), event_box);
+ gtk_widget_show (event_box);
+
+ /* Create a long label */
+
+ label = gtk_label_new ("Click here to quit, quit, quit, quit, quit");
+ gtk_container_add (GTK_CONTAINER (event_box), label);
+ gtk_widget_show (label);
+
+ /* Clip it short. */
+ gtk_widget_set_usize (label, 110, 20);
+
+ /* And bind an action to it */
+ gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK);
+ gtk_signal_connect (GTK_OBJECT(event_box), "button_press_event",
+ GTK_SIGNAL_FUNC (gtk_exit), NULL);
+
+ /* Yet one more thing you need an X window for ... */
+
+ gtk_widget_realize (event_box);
+ gdk_window_set_cursor (event_box->window, gdk_cursor_new (GDK_HAND1));
+
+ gtk_widget_show (window);
+
+ gtk_main ();
+
+ return(0);
+}
+/* example-end */
</verb></tscreen>
-These functions add pages to the notebook by inserting them from the
-back of the notebook (append), or the front of the notebook (prepend).
-<tt/child/ is the widget that is placed within the notebook page, and
-<tt/tab_label/ is the label for the page being added. The <tt/child/
-widget must be created separately, and is typically a set of options
-setout witin one of the other container widgets, such as a table.
+<!-- ----------------------------------------------------------------- -->
+<sect1> Fixed Container
+<p>
+The Fixed container allows you to place widgets at a fixed position
+within it's window, relative to it's upper left hand corner. The
+position of the widgets can be changed dynamically.
-The final function for adding a page to the notebook contains all of
-the properties of the previous two, but it allows you to specify what
-position you want the page to be in the notebook.
+There are only three functions associated with the fixed widget:
<tscreen><verb>
-void gtk_notebook_insert_page( GtkNotebook *notebook,
- GtkWidget *child,
- GtkWidget *tab_label,
- gint position );
+GtkWidget* gtk_fixed_new( void );
+
+void gtk_fixed_put( GtkFixed *fixed,
+ GtkWidget *widget,
+ gint16 x,
+ gint16 y );
+
+void gtk_fixed_move( GtkFixed *fixed,
+ GtkWidget *widget,
+ gint16 x,
+ gint16 y );
</verb></tscreen>
-The parameters are the same as _append_ and _prepend_ except it
-contains an extra parameter, <tt/position/. This parameter is used to
-specify what place this page will be inserted into.
+The function <tt/gtk_fixed_new/ allows you to create a new Fixed
+container.
-Now that we know how to add a page, lets see how we can remove a page
-from the notebook.
+<tt/gtk_fixed_put/ places <tt/widget/ in the container <tt/fixed/ at
+the position specified by <tt/x/ and <tt/y/.
+
+<tt/gtk_fixed_move/ allows the specified widget to be moved to a new
+position.
+
+The following example illustrates how to use the Fixed Container.
<tscreen><verb>
-void gtk_notebook_remove_page( GtkNotebook *notebook,
- gint page_num );
-</verb></tscreen>
+/* example-start fixed fixed.c */
-This function takes the page specified by <tt/page_num/ and removes it
-from the widget pointed to by <tt/notebook/.
+#include <gtk/gtk.h>
-To find out what the current page is in a notebook use the function:
+/* I'm going to be lazy and use some global variables to
+ * store the position of the widget within the fixed
+ * container */
+gint x=50;
+gint y=50;
-<tscreen><verb>
-gint gtk_notebook_get_current_page( GtkNotebook *notebook );
-</verb></tscreen>
+/* This callback function moves the button to a new position
+ * in the Fixed container. */
+void move_button( GtkWidget *widget,
+ GtkWidget *fixed )
+{
+ x = (x+30)%300;
+ y = (y+50)%300;
+ gtk_fixed_move( GTK_FIXED(fixed), widget, x, y);
+}
-These next two functions are simple calls to move the notebook page
-forward or backward. Simply provide the respective function call with
-the notebook widget you wish to operate on. Note: when the NoteBook is
-currently on the last page, and gtk_notebook_next_page is called, the
-notebook will wrap back to the first page. Likewise, if the NoteBook
-is on the first page, and gtk_notebook_prev_page is called, the
-notebook will wrap to the last page.
+int main( int argc,
+ char *argv[] )
+{
+ /* GtkWidget is the storage type for widgets */
+ GtkWidget *window;
+ GtkWidget *fixed;
+ GtkWidget *button;
+ gint i;
-<tscreen><verb>
-void gtk_notebook_next_page( GtkNoteBook *notebook );
+ /* Initialise GTK */
+ gtk_init(&argc, &argv);
+
+ /* Create a new window */
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(window), "Fixed Container");
-void gtk_notebook_prev_page( GtkNoteBook *notebook );
+ /* Here we connect the "destroy" event to a signal handler */
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
+
+ /* Sets the border width of the window. */
+ gtk_container_set_border_width (GTK_CONTAINER (window), 10);
+
+ /* Create a Fixed Container */
+ fixed = gtk_fixed_new();
+ gtk_container_add(GTK_CONTAINER(window), fixed);
+ gtk_widget_show(fixed);
+
+ for (i = 1 ; i <= 3 ; i++) {
+ /* Creates a new button with the label "Press me" */
+ button = gtk_button_new_with_label ("Press me");
+
+ /* When the button receives the "clicked" signal, it will call the
+ * function move_button() passing it the Fixed Containter as its
+ * argument. */
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (move_button), fixed);
+
+ /* This packs the button into the fixed containers window. */
+ gtk_fixed_put (GTK_FIXED (fixed), button, i*50, i*50);
+
+ /* The final step is to display this newly created widget. */
+ gtk_widget_show (button);
+ }
+
+ /* Display the window */
+ gtk_widget_show (window);
+
+ /* Enter the event loop */
+ gtk_main ();
+
+ return(0);
+}
+/* example-end */
</verb></tscreen>
-This next function sets the 'active' page. If you wish the notebook to
-be opened to page 5 for example, you would use this function. Without
-using this function, the notebook defaults to the first page.
+<!-- ----------------------------------------------------------------- -->
+<sect1> Frames
+<p>
+Frames can be used to enclose one or a group of widgets with a box
+which can optionally be labelled. The position of the label and the
+style of the box can be altered to suit.
+
+A Frame can be created with the following function:
<tscreen><verb>
-void gtk_notebook_set_page( GtkNotebook *notebook,
- gint page_num );
+GtkWidget *gtk_frame_new( const gchar *label );
</verb></tscreen>
-The next two functions add or remove the notebook page tabs and the
-notebook border respectively.
+The label is by default placed in the upper left hand corner of the
+frame. A value of NULL for the <tt/label/ argument will result in no
+label being displayed. The text of the label can be changed using the
+next function.
<tscreen><verb>
-void gtk_notebook_set_show_tabs( GtkNotebook *notebook,
- gboolean show_tabs);
+void gtk_frame_set_label( GtkFrame *frame,
+ const gchar *label );
+</verb></tscreen>
-void gtk_notebook_set_show_border( GtkNotebook *notebook,
- gboolean show_border );
+The position of the label can be changed using this function:
+
+<tscreen><verb>
+void gtk_frame_set_label_align( GtkFrame *frame,
+ gfloat xalign,
+ gfloat yalign );
</verb></tscreen>
-The next function is useful when the you have a large number of pages,
-and the tabs don't fit on the page. It allows the tabs to be scrolled
-through using two arrow buttons.
+<tt/xalign/ and <tt/yalign/ take values between 0.0 and 1.0. <tt/xalign/
+indicates the position of the label along the top horizontal of the
+frame. <tt/yalign/ is not currently used. The default value of xalign
+is 0.0 which places the label at the left hand end of the frame.
+
+The next function alters the style of the box that is used to outline
+the frame.
<tscreen><verb>
-void gtk_notebook_set_scrollable( GtkNotebook *notebook,
- gboolean scrollable );
+void gtk_frame_set_shadow_type( GtkFrame *frame,
+ GtkShadowType type);
</verb></tscreen>
-<tt/show_tabs/, <tt/show_border/ and <tt/scrollable/ can be either
-TRUE or FALSE.
+The <tt/type/ argument can take one of the following values:
+<itemize>
+<item> GTK_SHADOW_NONE
+<item> GTK_SHADOW_IN
+<item> GTK_SHADOW_OUT
+<item> GTK_SHADOW_ETCHED_IN (the default)
+<item> GTK_SHADOW_ETCHED_OUT
+</itemize>
-Now lets look at an example, it is expanded from the testgtk.c code
-that comes with the GTK distribution. This small program creates a
-window with a notebook and six buttons. The notebook contains 11
-pages, added in three different ways, appended, inserted, and
-prepended. The buttons allow you rotate the tab positions, add/remove
-the tabs and border, remove a page, change pages in both a forward and
-backward manner, and exit the program.
+The following code example illustrates the use of the Frame widget.
<tscreen><verb>
-/* example-start notebook notebook.c */
+/* example-start frame frame.c */
#include <gtk/gtk.h>
-/* This function rotates the position of the tabs */
-void rotate_book (GtkButton *button, GtkNotebook *notebook)
+int main( int argc,
+ char *argv[] )
{
- gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4);
-}
+ /* GtkWidget is the storage type for widgets */
+ GtkWidget *window;
+ GtkWidget *frame;
+ GtkWidget *button;
+ gint i;
-/* Add/Remove the page tabs and the borders */
-void tabsborder_book (GtkButton *button, GtkNotebook *notebook)
-{
- gint tval = FALSE;
- gint bval = FALSE;
- if (notebook->show_tabs == 0)
- tval = TRUE;
- if (notebook->show_border == 0)
- bval = TRUE;
+ /* Initialise GTK */
+ gtk_init(&argc, &argv);
- gtk_notebook_set_show_tabs (notebook, tval);
- gtk_notebook_set_show_border (notebook, bval);
-}
+ /* Create a new window */
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(window), "Frame Example");
-/* Remove a page from the notebook */
-void remove_book (GtkButton *button, GtkNotebook *notebook)
-{
- gint page;
-
- page = gtk_notebook_get_current_page(notebook);
- gtk_notebook_remove_page (notebook, page);
- /* Need to refresh the widget --
- This forces the widget to redraw itself. */
- gtk_widget_draw(GTK_WIDGET(notebook), NULL);
-}
+ /* Here we connect the "destroy" event to a signal handler */
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
-void delete (GtkWidget *widget, GtkWidget *event, gpointer data)
-{
- gtk_main_quit ();
-}
+ gtk_widget_set_usize(window, 300, 300);
+ /* Sets the border width of the window. */
+ gtk_container_set_border_width (GTK_CONTAINER (window), 10);
-int main (int argc, char *argv[])
-{
- GtkWidget *window;
- GtkWidget *button;
- GtkWidget *table;
- GtkWidget *notebook;
- GtkWidget *frame;
- GtkWidget *label;
- GtkWidget *checkbutton;
- int i;
- char bufferf[32];
- char bufferl[32];
-
- gtk_init (&argc, &argv);
-
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-
- gtk_signal_connect (GTK_OBJECT (window), "delete_event",
- GTK_SIGNAL_FUNC (delete), NULL);
-
- gtk_container_set_border_width (GTK_CONTAINER (window), 10);
+ /* Create a Frame */
+ frame = gtk_frame_new(NULL);
+ gtk_container_add(GTK_CONTAINER(window), frame);
- table = gtk_table_new(3,6,FALSE);
- gtk_container_add (GTK_CONTAINER (window), table);
-
- /* Create a new notebook, place the position of the tabs */
- notebook = gtk_notebook_new ();
- gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
- gtk_table_attach_defaults(GTK_TABLE(table), notebook, 0,6,0,1);
- gtk_widget_show(notebook);
-
- /* Lets append a bunch of pages to the notebook */
- for (i=0; i < 5; i++) {
- sprintf(bufferf, "Append Frame %d", i+1);
- sprintf(bufferl, "Page %d", i+1);
-
- frame = gtk_frame_new (bufferf);
- gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
- gtk_widget_set_usize (frame, 100, 75);
- gtk_widget_show (frame);
-
- label = gtk_label_new (bufferf);
- gtk_container_add (GTK_CONTAINER (frame), label);
- gtk_widget_show (label);
-
- label = gtk_label_new (bufferl);
- gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
- }
-
- /* Now lets add a page to a specific spot */
- checkbutton = gtk_check_button_new_with_label ("Check me please!");
- gtk_widget_set_usize(checkbutton, 100, 75);
- gtk_widget_show (checkbutton);
-
- label = gtk_label_new ("Add page");
- gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);
-
- /* Now finally lets prepend pages to the notebook */
- for (i=0; i < 5; i++) {
- sprintf(bufferf, "Prepend Frame %d", i+1);
- sprintf(bufferl, "PPage %d", i+1);
-
- frame = gtk_frame_new (bufferf);
- gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
- gtk_widget_set_usize (frame, 100, 75);
- gtk_widget_show (frame);
-
- label = gtk_label_new (bufferf);
- gtk_container_add (GTK_CONTAINER (frame), label);
- gtk_widget_show (label);
-
- label = gtk_label_new (bufferl);
- gtk_notebook_prepend_page (GTK_NOTEBOOK(notebook), frame, label);
- }
-
- /* Set what page to start at (page 4) */
- gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3);
+ /* Set the frames label */
+ gtk_frame_set_label( GTK_FRAME(frame), "GTK Frame Widget" );
- /* Create a bunch of buttons */
- button = gtk_button_new_with_label ("close");
- gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
- GTK_SIGNAL_FUNC (delete), NULL);
- gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,1,2);
- gtk_widget_show(button);
-
- button = gtk_button_new_with_label ("next page");
- gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
- (GtkSignalFunc) gtk_notebook_next_page,
- GTK_OBJECT (notebook));
- gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,1,2);
- gtk_widget_show(button);
-
- button = gtk_button_new_with_label ("prev page");
- gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
- (GtkSignalFunc) gtk_notebook_prev_page,
- GTK_OBJECT (notebook));
- gtk_table_attach_defaults(GTK_TABLE(table), button, 2,3,1,2);
- gtk_widget_show(button);
-
- button = gtk_button_new_with_label ("tab position");
- gtk_signal_connect (GTK_OBJECT (button), "clicked",
- (GtkSignalFunc) rotate_book, GTK_OBJECT(notebook));
- gtk_table_attach_defaults(GTK_TABLE(table), button, 3,4,1,2);
- gtk_widget_show(button);
-
- button = gtk_button_new_with_label ("tabs/border on/off");
- gtk_signal_connect (GTK_OBJECT (button), "clicked",
- (GtkSignalFunc) tabsborder_book,
- GTK_OBJECT (notebook));
- gtk_table_attach_defaults(GTK_TABLE(table), button, 4,5,1,2);
- gtk_widget_show(button);
-
- button = gtk_button_new_with_label ("remove page");
- gtk_signal_connect (GTK_OBJECT (button), "clicked",
- (GtkSignalFunc) remove_book,
- GTK_OBJECT(notebook));
- gtk_table_attach_defaults(GTK_TABLE(table), button, 5,6,1,2);
- gtk_widget_show(button);
-
- gtk_widget_show(table);
- gtk_widget_show(window);
+ /* Align the label at the right of the frame */
+ gtk_frame_set_label_align( GTK_FRAME(frame), 1.0, 0.0);
+
+ /* Set the style of the frame */
+ gtk_frame_set_shadow_type( GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT);
+
+ gtk_widget_show(frame);
+
+ /* Display the window */
+ gtk_widget_show (window);
- gtk_main ();
+ /* Enter the event loop */
+ gtk_main ();
- return(0);
+ return(0);
}
/* example-end */
-</verb></tscreen>
-
-Hopefully this helps you on your way with creating notebooks for your
-GTK applications.
-
-<!-- ----------------------------------------------------------------- -->
-<sect1>Scrolled Windows
-<p>
-Scrolled windows are used to create a scrollable area inside a real
-window. You may insert any type of widget into a scrolled window, and
-it will be accessible regardless of the size by using the scrollbars.
-The following function is used to create a new scrolled window.
-
-<tscreen><verb>
-GtkWidget *gtk_scrolled_window_new( GtkAdjustment *hadjustment,
- GtkAdjustment *vadjustment );
</verb></tscreen>
-Where the first argument is the adjustment for the horizontal
-direction, and the second, the adjustment for the vertical direction.
-These are almost always set to NULL.
-
+<!-- ----------------------------------------------------------------- -->
+<sect1> Aspect Frames
+<p>
+The aspect frame widget is like a frame widget, except that it also
+enforces the aspect ratio (that is, the ratio of the width to the
+height) of the child widget to have a certain value, adding extra
+space if necessary. This is useful, for instance, if you want to
+preview a larger image. The size of the preview should vary when the
+user resizes the window, but the aspect ratio needs to always match
+the original image.
+
+To create a new aspect frame use:
+
<tscreen><verb>
-void gtk_scrolled_window_set_policy( GtkScrolledWindow *scrolled_window,
- GtkPolicyType hscrollbar_policy,
- GtkPolicyType vscrollbar_policy );
+GtkWidget *gtk_aspect_frame_new( const gchar *label,
+ gfloat xalign,
+ gfloat yalign,
+ gfloat ratio,
+ gint obey_child);
</verb></tscreen>
-
-This sets the policy to be used with respect to the scrollbars.
-The first argument is the scrolled window you wish to change. The second
-sets the policy for the horizontal scrollbar, and the third the policy for
-the vertical scrollbar.
-
-The policy may be one of GTK_POLICY_AUTOMATIC, or GTK_POLICY_ALWAYS.
-GTK_POLICY_AUTOMATIC will automatically decide whether you need
-scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
-there.
-
-You can then place your object into the scrolled window using the
-following function.
-
+
+<tt/xalign/ and <tt/yalign/ specify alignment as with Alignment
+widgets. If <tt/obey_child/ is true, the aspect ratio of a child
+widget will match the aspect ratio of the ideal size it requests.
+Otherwise, it is given by <tt/ratio/.
+
+To change the options of an existing aspect frame, you can use:
+
<tscreen><verb>
-void gtk_scrolled_window_add_with_viewport( GtkScrolledWindow *scrolled_window,
- GtkWidget *child);
+void gtk_aspect_frame_set( GtkAspectFrame *aspect_frame,
+ gfloat xalign,
+ gfloat yalign,
+ gfloat ratio,
+ gint obey_child);
</verb></tscreen>
-
-Here is a simple example that packs 100 toggle buttons into a scrolled
-window. I've only commented on the parts that may be new to you.
-
+
+As an example, the following program uses an AspectFrame to present a
+drawing area whose aspect ratio will always be 2:1, no matter how the
+user resizes the top-level window.
+
<tscreen><verb>
-/* example-start scrolledwin scrolledwin.c */
+/* example-start aspectframe aspectframe.c */
#include <gtk/gtk.h>
-
-void destroy(GtkWidget *widget, gpointer data)
-{
- gtk_main_quit();
-}
-
-int main (int argc, char *argv[])
+
+int
+main (int argc, char *argv[])
{
- static GtkWidget *window;
- GtkWidget *scrolled_window;
- GtkWidget *table;
- GtkWidget *button;
- char buffer[32];
- int i, j;
-
+ GtkWidget *window;
+ GtkWidget *aspect_frame;
+ GtkWidget *drawing_area;
gtk_init (&argc, &argv);
-
- /* Create a new dialog window for the scrolled window to be
- * packed into. A dialog is just like a normal window except it has a
- * vbox and a horizontal separator packed into it. It's just a shortcut
- * for creating dialogs */
- window = gtk_dialog_new ();
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
gtk_signal_connect (GTK_OBJECT (window), "destroy",
- (GtkSignalFunc) destroy, NULL);
- gtk_window_set_title (GTK_WINDOW (window), "GtkScrolledWindow example");
- gtk_container_set_border_width (GTK_CONTAINER (window), 0);
- gtk_widget_set_usize(window, 300, 300);
-
- /* create a new scrolled window. */
- scrolled_window = gtk_scrolled_window_new (NULL, NULL);
-
- gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
-
- /* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS.
- * GTK_POLICY_AUTOMATIC will automatically decide whether you need
- * scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
- * there. The first one is the horizontal scrollbar, the second,
- * the vertical. */
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
- /* The dialog window is created with a vbox packed into it. */
- gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window,
- TRUE, TRUE, 0);
- gtk_widget_show (scrolled_window);
-
- /* create a table of 10 by 10 squares. */
- table = gtk_table_new (10, 10, FALSE);
-
- /* set the spacing to 10 on x and 10 on y */
- gtk_table_set_row_spacings (GTK_TABLE (table), 10);
- gtk_table_set_col_spacings (GTK_TABLE (table), 10);
-
- /* pack the table into the scrolled window */
- gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window),
- table);
- gtk_widget_show (table);
-
- /* this simply creates a grid of toggle buttons on the table
- * to demonstrate the scrolled window. */
- for (i = 0; i < 10; i++)
- for (j = 0; j < 10; j++) {
- sprintf (buffer, "button (%d,%d)\n", i, j);
- button = gtk_toggle_button_new_with_label (buffer);
- gtk_table_attach_defaults (GTK_TABLE (table), button,
- i, i+1, j, j+1);
- gtk_widget_show (button);
- }
-
- /* Add a "close" button to the bottom of the dialog */
- button = gtk_button_new_with_label ("close");
- gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
- (GtkSignalFunc) gtk_widget_destroy,
- GTK_OBJECT (window));
-
- /* this makes it so the button is the default. */
-
- GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
- gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0);
-
- /* This grabs this button to be the default button. Simply hitting
- * the "Enter" key will cause this button to activate. */
- gtk_widget_grab_default (button);
- gtk_widget_show (button);
-
+ GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
+ gtk_container_set_border_width (GTK_CONTAINER (window), 10);
+
+ /* Create an aspect_frame and add it to our toplevel window */
+
+ aspect_frame = gtk_aspect_frame_new ("2x1", /* label */
+ 0.5, /* center x */
+ 0.5, /* center y */
+ 2, /* xsize/ysize = 2 */
+ FALSE /* ignore child's aspect */);
+
+ gtk_container_add (GTK_CONTAINER(window), aspect_frame);
+ gtk_widget_show (aspect_frame);
+
+ /* Now add a child widget to the aspect frame */
+
+ drawing_area = gtk_drawing_area_new ();
+
+ /* Ask for a 200x200 window, but the AspectFrame will give us a 200x100
+ * window since we are forcing a 2x1 aspect ratio */
+ gtk_widget_set_usize (drawing_area, 200, 200);
+ gtk_container_add (GTK_CONTAINER(aspect_frame), drawing_area);
+ gtk_widget_show (drawing_area);
+
gtk_widget_show (window);
-
- gtk_main();
-
- return(0);
+ gtk_main ();
+ return 0;
}
/* example-end */
</verb></tscreen>
-Try playing with resizing the window. You'll notice how the scrollbars
-react. You may also wish to use the gtk_widget_set_usize() call to set
-the default size of the window or other widgets.
-
<!-- ----------------------------------------------------------------- -->
<sect1> Paned Window Widgets
<p>
/* example-end */
</verb></tscreen>
+<!-- ----------------------------------------------------------------- -->
+<sect1>Scrolled Windows
+<p>
+Scrolled windows are used to create a scrollable area inside a real
+window. You may insert any type of widget into a scrolled window, and
+it will be accessible regardless of the size by using the scrollbars.
+
+The following function is used to create a new scrolled window.
+
+<tscreen><verb>
+GtkWidget *gtk_scrolled_window_new( GtkAdjustment *hadjustment,
+ GtkAdjustment *vadjustment );
+</verb></tscreen>
+
+Where the first argument is the adjustment for the horizontal
+direction, and the second, the adjustment for the vertical direction.
+These are almost always set to NULL.
+
+<tscreen><verb>
+void gtk_scrolled_window_set_policy( GtkScrolledWindow *scrolled_window,
+ GtkPolicyType hscrollbar_policy,
+ GtkPolicyType vscrollbar_policy );
+</verb></tscreen>
+
+This sets the policy to be used with respect to the scrollbars.
+The first argument is the scrolled window you wish to change. The second
+sets the policy for the horizontal scrollbar, and the third the policy for
+the vertical scrollbar.
+
+The policy may be one of GTK_POLICY_AUTOMATIC, or GTK_POLICY_ALWAYS.
+GTK_POLICY_AUTOMATIC will automatically decide whether you need
+scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
+there.
+
+You can then place your object into the scrolled window using the
+following function.
+
+<tscreen><verb>
+void gtk_scrolled_window_add_with_viewport( GtkScrolledWindow *scrolled_window,
+ GtkWidget *child);
+</verb></tscreen>
+
+Here is a simple example that packs 100 toggle buttons into a scrolled
+window. I've only commented on the parts that may be new to you.
+
+<tscreen><verb>
+/* example-start scrolledwin scrolledwin.c */
+
+#include <gtk/gtk.h>
+
+void destroy(GtkWidget *widget, gpointer data)
+{
+ gtk_main_quit();
+}
+
+int main (int argc, char *argv[])
+{
+ static GtkWidget *window;
+ GtkWidget *scrolled_window;
+ GtkWidget *table;
+ GtkWidget *button;
+ char buffer[32];
+ int i, j;
+
+ gtk_init (&argc, &argv);
+
+ /* Create a new dialog window for the scrolled window to be
+ * packed into. A dialog is just like a normal window except it has a
+ * vbox and a horizontal separator packed into it. It's just a shortcut
+ * for creating dialogs */
+ window = gtk_dialog_new ();
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ (GtkSignalFunc) destroy, NULL);
+ gtk_window_set_title (GTK_WINDOW (window), "GtkScrolledWindow example");
+ gtk_container_set_border_width (GTK_CONTAINER (window), 0);
+ gtk_widget_set_usize(window, 300, 300);
+
+ /* create a new scrolled window. */
+ scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+
+ gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
+
+ /* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS.
+ * GTK_POLICY_AUTOMATIC will automatically decide whether you need
+ * scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars
+ * there. The first one is the horizontal scrollbar, the second,
+ * the vertical. */
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+ /* The dialog window is created with a vbox packed into it. */
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG(window)->vbox), scrolled_window,
+ TRUE, TRUE, 0);
+ gtk_widget_show (scrolled_window);
+
+ /* create a table of 10 by 10 squares. */
+ table = gtk_table_new (10, 10, FALSE);
+
+ /* set the spacing to 10 on x and 10 on y */
+ gtk_table_set_row_spacings (GTK_TABLE (table), 10);
+ gtk_table_set_col_spacings (GTK_TABLE (table), 10);
+
+ /* pack the table into the scrolled window */
+ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window),
+ table);
+ gtk_widget_show (table);
+
+ /* this simply creates a grid of toggle buttons on the table
+ * to demonstrate the scrolled window. */
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++) {
+ sprintf (buffer, "button (%d,%d)\n", i, j);
+ button = gtk_toggle_button_new_with_label (buffer);
+ gtk_table_attach_defaults (GTK_TABLE (table), button,
+ i, i+1, j, j+1);
+ gtk_widget_show (button);
+ }
+
+ /* Add a "close" button to the bottom of the dialog */
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_widget_destroy,
+ GTK_OBJECT (window));
+
+ /* this makes it so the button is the default. */
+
+ GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+ gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, TRUE, TRUE, 0);
+
+ /* This grabs this button to be the default button. Simply hitting
+ * the "Enter" key will cause this button to activate. */
+ gtk_widget_grab_default (button);
+ gtk_widget_show (button);
+
+ gtk_widget_show (window);
+
+ gtk_main();
+
+ return(0);
+}
+/* example-end */
+</verb></tscreen>
+
+Try playing with resizing the window. You'll notice how the scrollbars
+react. You may also wish to use the gtk_widget_set_usize() call to set
+the default size of the window or other widgets.
+
<!-- ----------------------------------------------------------------- -->
<sect1>Toolbar
<p>
".............++++..............."};
</verb></tscreen>
-<!-- ----------------------------------------------------------------- -->
-<sect1> Aspect Frames
+<!-- ----------------------------------------------------------------- -->
+<sect1> Notebooks
<p>
-The aspect frame widget is like a frame widget, except that it also
-enforces the aspect ratio (that is, the ratio of the width to the
-height) of the child widget to have a certain value, adding extra
-space if necessary. This is useful, for instance, if you want to
-preview a larger image. The size of the preview should vary when the
-user resizes the window, but the aspect ratio needs to always match
-the original image.
-
-To create a new aspect frame use:
-
-<tscreen><verb>
-GtkWidget *gtk_aspect_frame_new( const gchar *label,
- gfloat xalign,
- gfloat yalign,
- gfloat ratio,
- gint obey_child);
-</verb></tscreen>
-
-<tt/xalign/ and <tt/yalign/ specify alignment as with Alignment
-widgets. If <tt/obey_child/ is true, the aspect ratio of a child
-widget will match the aspect ratio of the ideal size it requests.
-Otherwise, it is given by <tt/ratio/.
-
-To change the options of an existing aspect frame, you can use:
-
+The NoteBook Widget is a collection of 'pages' that overlap each
+other, each page contains different information. This widget has
+become more common lately in GUI programming, and it is a good way to
+show blocks of similar information that warrant separation in their
+display.
+
+The first function call you will need to know, as you can probably
+guess by now, is used to create a new notebook widget.
+
<tscreen><verb>
-void gtk_aspect_frame_set( GtkAspectFrame *aspect_frame,
- gfloat xalign,
- gfloat yalign,
- gfloat ratio,
- gint obey_child);
+GtkWidget *gtk_notebook_new( void );
</verb></tscreen>
-
-As an example, the following program uses an AspectFrame to present a
-drawing area whose aspect ratio will always be 2:1, no matter how the
-user resizes the top-level window.
-
-<tscreen><verb>
-/* example-start aspectframe aspectframe.c */
-#include <gtk/gtk.h>
-
-int
-main (int argc, char *argv[])
-{
- GtkWidget *window;
- GtkWidget *aspect_frame;
- GtkWidget *drawing_area;
- gtk_init (&argc, &argv);
-
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
- gtk_signal_connect (GTK_OBJECT (window), "destroy",
- GTK_SIGNAL_FUNC (gtk_main_quit), NULL);
- gtk_container_set_border_width (GTK_CONTAINER (window), 10);
-
- /* Create an aspect_frame and add it to our toplevel window */
-
- aspect_frame = gtk_aspect_frame_new ("2x1", /* label */
- 0.5, /* center x */
- 0.5, /* center y */
- 2, /* xsize/ysize = 2 */
- FALSE /* ignore child's aspect */);
-
- gtk_container_add (GTK_CONTAINER(window), aspect_frame);
- gtk_widget_show (aspect_frame);
-
- /* Now add a child widget to the aspect frame */
-
- drawing_area = gtk_drawing_area_new ();
-
- /* Ask for a 200x200 window, but the AspectFrame will give us a 200x100
- * window since we are forcing a 2x1 aspect ratio */
- gtk_widget_set_usize (drawing_area, 200, 200);
- gtk_container_add (GTK_CONTAINER(aspect_frame), drawing_area);
- gtk_widget_show (drawing_area);
-
- gtk_widget_show (window);
- gtk_main ();
- return 0;
-}
-/* example-end */
+Once the notebook has been created, there are a number of functions
+that operate on the notebook widget. Let's look at them individually.
+
+The first one we will look at is how to position the page indicators.
+These page indicators or 'tabs' as they are referred to, can be
+positioned in four ways: top, bottom, left, or right.
+
+<tscreen><verb>
+void gtk_notebook_set_tab_pos( GtkNotebook *notebook,
+ GtkPositionType pos );
</verb></tscreen>
-<!-- ----------------------------------------------------------------- -->
-<sect1>The EventBox <label id="sec_EventBox">
-<p>
-Some gtk widgets don't have associated X windows, so they just draw on
-their parents. Because of this, they cannot receive events and if they
-are incorrectly sized, they don't clip so you can get messy
-overwriting etc. If you require more from these widgets, the EventBox
-is for you.
+GtkPostionType will be one of the following, and they are pretty self explanatory:
+<itemize>
+<item> GTK_POS_LEFT
+<item> GTK_POS_RIGHT
+<item> GTK_POS_TOP
+<item> GTK_POS_BOTTOM
+</itemize>
-At first glance, the EventBox widget might appear to be totally
-useless. It draws nothing on the screen and responds to no
-events. However, it does serve a function - it provides an X window
-for its child widget. This is important as many GTK widgets do not
-have an associated X window. Not having an X window saves memory and
-improves performance, but also has some drawbacks. A widget without an
-X window cannot receive events, and does not perform any clipping on
-its contents. Although the name <em/EventBox/ emphasizes the
-event-handling function, the widget can also be used for clipping.
-(and more, see the example below).
+GTK_POS_TOP is the default.
-To create a new EventBox widget, use:
+Next we will look at how to add pages to the notebook. There are three
+ways to add pages to the NoteBook. Let's look at the first two
+together as they are quite similar.
<tscreen><verb>
-GtkWidget *gtk_event_box_new( void );
+void gtk_notebook_append_page( GtkNotebook *notebook,
+ GtkWidget *child,
+ GtkWidget *tab_label );
+
+void gtk_notebook_prepend_page( GtkNotebook *notebook,
+ GtkWidget *child,
+ GtkWidget *tab_label );
</verb></tscreen>
-A child widget can then be added to this EventBox:
+These functions add pages to the notebook by inserting them from the
+back of the notebook (append), or the front of the notebook (prepend).
+<tt/child/ is the widget that is placed within the notebook page, and
+<tt/tab_label/ is the label for the page being added. The <tt/child/
+widget must be created separately, and is typically a set of options
+setout witin one of the other container widgets, such as a table.
+
+The final function for adding a page to the notebook contains all of
+the properties of the previous two, but it allows you to specify what
+position you want the page to be in the notebook.
<tscreen><verb>
-gtk_container_add( GTK_CONTAINER(event_box), widget );
+void gtk_notebook_insert_page( GtkNotebook *notebook,
+ GtkWidget *child,
+ GtkWidget *tab_label,
+ gint position );
</verb></tscreen>
-The following example demonstrates both uses of an EventBox - a label
-is created that is clipped to a small box, and set up so that a
-mouse-click on the label causes the program to exit. Resizing the
-window reveals varying amounts of the label.
-
-<tscreen><verb>
-/* example-start eventbox eventbox.c */
+The parameters are the same as _append_ and _prepend_ except it
+contains an extra parameter, <tt/position/. This parameter is used to
+specify what place this page will be inserted into.
-#include <gtk/gtk.h>
+Now that we know how to add a page, lets see how we can remove a page
+from the notebook.
-int
-main (int argc, char *argv[])
-{
- GtkWidget *window;
- GtkWidget *event_box;
- GtkWidget *label;
-
- gtk_init (&argc, &argv);
-
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-
- gtk_window_set_title (GTK_WINDOW (window), "Event Box");
-
- gtk_signal_connect (GTK_OBJECT (window), "destroy",
- GTK_SIGNAL_FUNC (gtk_exit), NULL);
-
- gtk_container_set_border_width (GTK_CONTAINER (window), 10);
-
- /* Create an EventBox and add it to our toplevel window */
-
- event_box = gtk_event_box_new ();
- gtk_container_add (GTK_CONTAINER(window), event_box);
- gtk_widget_show (event_box);
-
- /* Create a long label */
-
- label = gtk_label_new ("Click here to quit, quit, quit, quit, quit");
- gtk_container_add (GTK_CONTAINER (event_box), label);
- gtk_widget_show (label);
-
- /* Clip it short. */
- gtk_widget_set_usize (label, 110, 20);
-
- /* And bind an action to it */
- gtk_widget_set_events (event_box, GDK_BUTTON_PRESS_MASK);
- gtk_signal_connect (GTK_OBJECT(event_box), "button_press_event",
- GTK_SIGNAL_FUNC (gtk_exit), NULL);
-
- /* Yet one more thing you need an X window for ... */
-
- gtk_widget_realize (event_box);
- gdk_window_set_cursor (event_box->window, gdk_cursor_new (GDK_HAND1));
-
- gtk_widget_show (window);
-
- gtk_main ();
-
- return(0);
-}
-/* example-end */
+<tscreen><verb>
+void gtk_notebook_remove_page( GtkNotebook *notebook,
+ gint page_num );
</verb></tscreen>
-<!-- ***************************************************************** -->
-<sect>CList Widget
-<!-- ***************************************************************** -->
-
-<!-- ----------------------------------------------------------------- -->
-<p>
-The GtkCList widget has replaced the GtkList widget (which is still
-available).
+This function takes the page specified by <tt/page_num/ and removes it
+from the widget pointed to by <tt/notebook/.
-The GtkCList widget is a multi-column list widget that is capable of
-handling literally thousands of rows of information. Each column can
-optionally have a title, which itself is optionally active, allowing
-us to bind a function to its selection.
+To find out what the current page is in a notebook use the function:
-<!-- ----------------------------------------------------------------- -->
-<sect1>Creating a GtkCList widget
-<p>
-Creating a GtkCList is quite straightforward, once you have learned
-about widgets in general. It provides the almost standard two ways,
-that is the hard way, and the easy way. But before we create it, there
-is one thing we should figure out beforehand: how many columns should
-it have?
+<tscreen><verb>
+gint gtk_notebook_get_current_page( GtkNotebook *notebook );
+</verb></tscreen>
-Not all columns have to be visible and can be used to store data that
-is related to a certain cell in the list.
+These next two functions are simple calls to move the notebook page
+forward or backward. Simply provide the respective function call with
+the notebook widget you wish to operate on. Note: when the NoteBook is
+currently on the last page, and gtk_notebook_next_page is called, the
+notebook will wrap back to the first page. Likewise, if the NoteBook
+is on the first page, and gtk_notebook_prev_page is called, the
+notebook will wrap to the last page.
<tscreen><verb>
-GtkWidget *gtk_clist_new ( gint columns );
+void gtk_notebook_next_page( GtkNoteBook *notebook );
-GtkWidget *gtk_clist_new_with_titles( gint columns,
- gchar *titles[] );
+void gtk_notebook_prev_page( GtkNoteBook *notebook );
</verb></tscreen>
-The first form is very straight forward, the second might require some
-explanation. Each column can have a title associated with it, and this
-title can be a label or a button that reacts when we click on it. If
-we use the second form, we must provide pointers to the title texts,
-and the number of pointers should equal the number of columns
-specified. Of course we can always use the first form, and manually
+This next function sets the 'active' page. If you wish the notebook to
+be opened to page 5 for example, you would use this function. Without
+using this function, the notebook defaults to the first page.
+
+<tscreen><verb>
+void gtk_notebook_set_page( GtkNotebook *notebook,
+ gint page_num );
+</verb></tscreen>
+
+The next two functions add or remove the notebook page tabs and the
+notebook border respectively.
+
+<tscreen><verb>
+void gtk_notebook_set_show_tabs( GtkNotebook *notebook,
+ gboolean show_tabs);
+
+void gtk_notebook_set_show_border( GtkNotebook *notebook,
+ gboolean show_border );
+</verb></tscreen>
+
+The next function is useful when the you have a large number of pages,
+and the tabs don't fit on the page. It allows the tabs to be scrolled
+through using two arrow buttons.
+
+<tscreen><verb>
+void gtk_notebook_set_scrollable( GtkNotebook *notebook,
+ gboolean scrollable );
+</verb></tscreen>
+
+<tt/show_tabs/, <tt/show_border/ and <tt/scrollable/ can be either
+TRUE or FALSE.
+
+Now lets look at an example, it is expanded from the testgtk.c code
+that comes with the GTK distribution. This small program creates a
+window with a notebook and six buttons. The notebook contains 11
+pages, added in three different ways, appended, inserted, and
+prepended. The buttons allow you rotate the tab positions, add/remove
+the tabs and border, remove a page, change pages in both a forward and
+backward manner, and exit the program.
+
+<tscreen><verb>
+/* example-start notebook notebook.c */
+
+#include <gtk/gtk.h>
+
+/* This function rotates the position of the tabs */
+void rotate_book (GtkButton *button, GtkNotebook *notebook)
+{
+ gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos +1) %4);
+}
+
+/* Add/Remove the page tabs and the borders */
+void tabsborder_book (GtkButton *button, GtkNotebook *notebook)
+{
+ gint tval = FALSE;
+ gint bval = FALSE;
+ if (notebook->show_tabs == 0)
+ tval = TRUE;
+ if (notebook->show_border == 0)
+ bval = TRUE;
+
+ gtk_notebook_set_show_tabs (notebook, tval);
+ gtk_notebook_set_show_border (notebook, bval);
+}
+
+/* Remove a page from the notebook */
+void remove_book (GtkButton *button, GtkNotebook *notebook)
+{
+ gint page;
+
+ page = gtk_notebook_get_current_page(notebook);
+ gtk_notebook_remove_page (notebook, page);
+ /* Need to refresh the widget --
+ This forces the widget to redraw itself. */
+ gtk_widget_draw(GTK_WIDGET(notebook), NULL);
+}
+
+void delete (GtkWidget *widget, GtkWidget *event, gpointer data)
+{
+ gtk_main_quit ();
+}
+
+int main (int argc, char *argv[])
+{
+ GtkWidget *window;
+ GtkWidget *button;
+ GtkWidget *table;
+ GtkWidget *notebook;
+ GtkWidget *frame;
+ GtkWidget *label;
+ GtkWidget *checkbutton;
+ int i;
+ char bufferf[32];
+ char bufferl[32];
+
+ gtk_init (&argc, &argv);
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_signal_connect (GTK_OBJECT (window), "delete_event",
+ GTK_SIGNAL_FUNC (delete), NULL);
+
+ gtk_container_set_border_width (GTK_CONTAINER (window), 10);
+
+ table = gtk_table_new(3,6,FALSE);
+ gtk_container_add (GTK_CONTAINER (window), table);
+
+ /* Create a new notebook, place the position of the tabs */
+ notebook = gtk_notebook_new ();
+ gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
+ gtk_table_attach_defaults(GTK_TABLE(table), notebook, 0,6,0,1);
+ gtk_widget_show(notebook);
+
+ /* Lets append a bunch of pages to the notebook */
+ for (i=0; i < 5; i++) {
+ sprintf(bufferf, "Append Frame %d", i+1);
+ sprintf(bufferl, "Page %d", i+1);
+
+ frame = gtk_frame_new (bufferf);
+ gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
+ gtk_widget_set_usize (frame, 100, 75);
+ gtk_widget_show (frame);
+
+ label = gtk_label_new (bufferf);
+ gtk_container_add (GTK_CONTAINER (frame), label);
+ gtk_widget_show (label);
+
+ label = gtk_label_new (bufferl);
+ gtk_notebook_append_page (GTK_NOTEBOOK (notebook), frame, label);
+ }
+
+ /* Now lets add a page to a specific spot */
+ checkbutton = gtk_check_button_new_with_label ("Check me please!");
+ gtk_widget_set_usize(checkbutton, 100, 75);
+ gtk_widget_show (checkbutton);
+
+ label = gtk_label_new ("Add page");
+ gtk_notebook_insert_page (GTK_NOTEBOOK (notebook), checkbutton, label, 2);
+
+ /* Now finally lets prepend pages to the notebook */
+ for (i=0; i < 5; i++) {
+ sprintf(bufferf, "Prepend Frame %d", i+1);
+ sprintf(bufferl, "PPage %d", i+1);
+
+ frame = gtk_frame_new (bufferf);
+ gtk_container_set_border_width (GTK_CONTAINER (frame), 10);
+ gtk_widget_set_usize (frame, 100, 75);
+ gtk_widget_show (frame);
+
+ label = gtk_label_new (bufferf);
+ gtk_container_add (GTK_CONTAINER (frame), label);
+ gtk_widget_show (label);
+
+ label = gtk_label_new (bufferl);
+ gtk_notebook_prepend_page (GTK_NOTEBOOK(notebook), frame, label);
+ }
+
+ /* Set what page to start at (page 4) */
+ gtk_notebook_set_page (GTK_NOTEBOOK(notebook), 3);
+
+ /* Create a bunch of buttons */
+ button = gtk_button_new_with_label ("close");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (delete), NULL);
+ gtk_table_attach_defaults(GTK_TABLE(table), button, 0,1,1,2);
+ gtk_widget_show(button);
+
+ button = gtk_button_new_with_label ("next page");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_notebook_next_page,
+ GTK_OBJECT (notebook));
+ gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2,1,2);
+ gtk_widget_show(button);
+
+ button = gtk_button_new_with_label ("prev page");
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) gtk_notebook_prev_page,
+ GTK_OBJECT (notebook));
+ gtk_table_attach_defaults(GTK_TABLE(table), button, 2,3,1,2);
+ gtk_widget_show(button);
+
+ button = gtk_button_new_with_label ("tab position");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) rotate_book, GTK_OBJECT(notebook));
+ gtk_table_attach_defaults(GTK_TABLE(table), button, 3,4,1,2);
+ gtk_widget_show(button);
+
+ button = gtk_button_new_with_label ("tabs/border on/off");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) tabsborder_book,
+ GTK_OBJECT (notebook));
+ gtk_table_attach_defaults(GTK_TABLE(table), button, 4,5,1,2);
+ gtk_widget_show(button);
+
+ button = gtk_button_new_with_label ("remove page");
+ gtk_signal_connect (GTK_OBJECT (button), "clicked",
+ (GtkSignalFunc) remove_book,
+ GTK_OBJECT(notebook));
+ gtk_table_attach_defaults(GTK_TABLE(table), button, 5,6,1,2);
+ gtk_widget_show(button);
+
+ gtk_widget_show(table);
+ gtk_widget_show(window);
+
+ gtk_main ();
+
+ return(0);
+}
+/* example-end */
+</verb></tscreen>
+
+Hopefully this helps you on your way with creating notebooks for your
+GTK applications.
+
+<!-- ***************************************************************** -->
+<sect>CList Widget
+<!-- ***************************************************************** -->
+
+<!-- ----------------------------------------------------------------- -->
+<p>
+The GtkCList widget has replaced the GtkList widget (which is still
+available).
+
+The GtkCList widget is a multi-column list widget that is capable of
+handling literally thousands of rows of information. Each column can
+optionally have a title, which itself is optionally active, allowing
+us to bind a function to its selection.
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>Creating a GtkCList widget
+<p>
+Creating a GtkCList is quite straightforward, once you have learned
+about widgets in general. It provides the almost standard two ways,
+that is the hard way, and the easy way. But before we create it, there
+is one thing we should figure out beforehand: how many columns should
+it have?
+
+Not all columns have to be visible and can be used to store data that
+is related to a certain cell in the list.
+
+<tscreen><verb>
+GtkWidget *gtk_clist_new ( gint columns );
+
+GtkWidget *gtk_clist_new_with_titles( gint columns,
+ gchar *titles[] );
+</verb></tscreen>
+
+The first form is very straight forward, the second might require some
+explanation. Each column can have a title associated with it, and this
+title can be a label or a button that reacts when we click on it. If
+we use the second form, we must provide pointers to the title texts,
+and the number of pointers should equal the number of columns
+specified. Of course we can always use the first form, and manually
add titles later.
Note: the GtkCList widget does not have it's own scrollbars and should
</verb></tscreen>
<!-- ***************************************************************** -->
-<sect> List Widget
+<sect> Tree Widget<label id="sec_Tree_Widgets">
<!-- ***************************************************************** -->
<p>
-NOTE: The GtkList widget has been superseded by the GtkCList widget.
-
-The GtkList widget is designed to act as a vertical container for
-widgets that should be of the type GtkListItem.
+The purpose of tree widgets is to display hierarchically-organized
+data. The GtkTree widget itself is a vertical container for widgets of
+type GtkTreeItem. GtkTree itself is not terribly different from
+GtkList - both are derived directly from GtkContainer, and the
+GtkContainer methods work in the same way on GtkTree widgets as on
+GtkList widgets. The difference is that GtkTree widgets can be nested
+within other GtkTree widgets. We'll see how to do this shortly.
-A GtkList widget has its own window to receive events and its own
-background color which is usually white. As it is directly derived
-from a GtkContainer it can be treated as such by using the
-GTK_CONTAINER(List) macro, see the GtkContainer widget for more on
-this. One should already be familiar with the usage of a GList and
-its related functions g_list_*() to be able to use the GtkList widget
-to it full extent.
+The GtkTree widget has its own window, and defaults to a white
+background, as does GtkList. Also, most of the GtkTree methods work in
+the same way as the corresponding GtkList ones. However, GtkTree is
+not derived from GtkList, so you cannot use them interchangeably.
-There is one field inside the structure definition of the GtkList
-widget that will be of greater interest to us, this is:
+<sect1> Creating a Tree
+<p>
+A GtkTree is created in the usual way, using:
<tscreen><verb>
-struct _GtkList
-{
- ...
- GList *selection;
- guint selection_mode;
- ...
-};
+GtkWidget* gtk_tree_new( void );
</verb></tscreen>
-The selection field of a GtkList points to a linked list of all items
-that are currently selected, or NULL if the selection is empty. So to
-learn about the current selection we read the GTK_LIST()->selection
-field, but do not modify it since the internal fields are maintained
-by the gtk_list_*() functions.
+Like the GtkList widget, a GtkTree will simply keep growing as more
+items are added to it, as well as when subtrees are expanded. For
+this reason, they are almost always packed into a
+GtkScrolledWindow. You might want to use gtk_widget_set_usize() on the
+scrolled window to ensure that it is big enough to see the tree's
+items, as the default size for GtkScrolledWindow is quite small.
-The selection_mode of the GtkList determines the selection facilities
-of a GtkList and therefore the contents of the GTK_LIST()->selection
-field. The selection_mode may be one of the following:
+Now that you have a tree, you'll probably want to add some items to
+it. <ref id="sec_Tree_Item_Widget" name="The Tree Item Widget"> below
+explains the gory details of GtkTreeItem. For now, it'll suffice to
+create one, using:
-<itemize>
-<item> GTK_SELECTION_SINGLE - The selection is either NULL
- or contains a GList pointer
- for a single selected item.
+<tscreen><verb>
+GtkWidget* gtk_tree_item_new_with_label( gchar *label );
+</verb></tscreen>
-<item> GTK_SELECTION_BROWSE - The selection is NULL if the list
- contains no widgets or insensitive
- ones only, otherwise it contains
- a GList pointer for one GList
- structure, and therefore exactly
- one list item.
+You can then add it to the tree using one of the following (see
+<ref id="sec_GtkTree_Functions" name="Functions and Macros">
+below for more options):
-<item> GTK_SELECTION_MULTIPLE - The selection is NULL if no list
- items are selected or a GList pointer
- for the first selected item. That
- in turn points to a GList structure
- for the second selected item and so
- on.
+<tscreen><verb>
+void gtk_tree_append( GtkTree *tree,
+ GtkWidget *tree_item );
-<item> GTK_SELECTION_EXTENDED - The selection is always NULL.
-</itemize>
+void gtk_tree_prepend( GtkTree *tree,
+ GtkWidget *tree_item );
+</verb></tscreen>
-The default is GTK_SELECTION_MULTIPLE.
+Note that you must add items to a GtkTree one at a time - there is no
+equivalent to gtk_list_*_items().
<!-- ----------------------------------------------------------------- -->
-<sect1> Signals
+<sect1> Adding a Subtree
<p>
+A subtree is created like any other GtkTree widget. A subtree is added
+to another tree beneath a tree item, using:
+
<tscreen><verb>
-void selection_changed( GtkList *list );
+void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
+ GtkWidget *subtree );
</verb></tscreen>
-This signal will be invoked whenever the selection field of a GtkList
-has changed. This happens when a child of the GtkList got selected or
-deselected.
+You do not need to call gtk_widget_show() on a subtree before or after
+adding it to a GtkTreeItem. However, you <em>must</em> have added the
+GtkTreeItem in question to a parent tree before calling
+gtk_tree_item_set_subtree(). This is because, technically, the parent
+of the subtree is <em>not</em> the GtkTreeItem which "owns" it, but
+rather the GtkTree which holds that GtkTreeItem.
-<tscreen><verb>
-void select_child( GtkList *list,
- GtkWidget *child);
-</verb></tscreen>
+When you add a subtree to a GtkTreeItem, a plus or minus sign appears
+beside it, which the user can click on to "expand" or "collapse" it,
+meaning, to show or hide its subtree. GtkTreeItems are collapsed by
+default. Note that when you collapse a GtkTreeItem, any selected
+items in its subtree remain selected, which may not be what the user
+expects.
-This signal is invoked when a child of the GtkList is about to get
-selected. This happens mainly on calls to gtk_list_select_item(),
-gtk_list_select_child(), button presses and sometimes indirectly
-triggered on some else occasions where children get added to or
-removed from the GtkList.
+<!-- ----------------------------------------------------------------- -->
+<sect1> Handling the Selection List
+<p>
+As with GtkList, the GtkTree type has a <tt>selection</tt> field, and
+it is possible to control the behaviour of the tree (somewhat) by
+setting the selection type using:
<tscreen><verb>
-void unselect_child( GtkList *list,
- GtkWidget *child );
+void gtk_tree_set_selection_mode( GtkTree *tree,
+ GtkSelectionMode mode );
</verb></tscreen>
-This signal is invoked when a child of the GtkList is about to get
-deselected. This happens mainly on calls to gtk_list_unselect_item(),
-gtk_list_unselect_child(), button presses and sometimes indirectly
-triggered on some else occasions where children get added to or
-removed from the GtkList.
+The semantics associated with the various selection modes are
+described in the section on the GtkList widget. As with the GtkList
+widget, the "select_child", "unselect_child" (not really - see <ref
+id="sec_GtkTree_Signals" name="Signals"> below for an explanation),
+and "selection_changed" signals are emitted when list items are
+selected or unselected. However, in order to take advantage of these
+signals, you need to know <em>which</em> GtkTree widget they will be
+emitted by, and where to find the list of selected items.
-<!-- ----------------------------------------------------------------- -->
-<sect1> Functions
+This is a source of potential confusion. The best way to explain this
+is that though all GtkTree widgets are created equal, some are more
+equal than others. All GtkTree widgets have their own X window, and
+can therefore receive events such as mouse clicks (if their
+GtkTreeItems or their children don't catch them first!). However, to
+make GTK_SELECTION_SINGLE and GTK_SELECTION_BROWSE selection types
+behave in a sane manner, the list of selected items is specific to the
+topmost GtkTree widget in a hierarchy, known as the "root tree".
+
+Thus, accessing the <tt>selection</tt>field directly in an arbitrary
+GtkTree widget is not a good idea unless you <em>know</em> it's the
+root tree. Instead, use the GTK_TREE_SELECTION (Tree) macro, which
+gives the root tree's selection list as a GList pointer. Of course,
+this list can include items that are not in the subtree in question if
+the selection type is GTK_SELECTION_MULTIPLE.
+
+Finally, the "select_child" (and "unselect_child", in theory) signals
+are emitted by all trees, but the "selection_changed" signal is only
+emitted by the root tree. Consequently, if you want to handle the
+"select_child" signal for a tree and all its subtrees, you will have
+to call gtk_signal_connect() for every subtree.
+
+<sect1> Tree Widget Internals
<p>
+The GtkTree's struct definition looks like this:
+
<tscreen><verb>
-guint gtk_list_get_type( void );
+struct _GtkTree
+{
+ GtkContainer container;
+
+ GList *children;
+
+ GtkTree* root_tree; /* owner of selection list */
+ GtkWidget* tree_owner;
+ GList *selection;
+ guint level;
+ guint indent_value;
+ guint current_indent;
+ guint selection_mode : 2;
+ guint view_mode : 1;
+ guint view_line : 1;
+};
</verb></tscreen>
-Returns the `GtkList' type identifier.
+The perils associated with accessing the <tt>selection</tt> field
+directly have already been mentioned. The other important fields of
+the struct can also be accessed with handy macros or class functions.
+GTK_TREE_IS_ROOT_TREE (Tree) returns a boolean value which indicates
+whether a tree is the root tree in a GtkTree hierarchy, while
+GTK_TREE_ROOT_TREE (Tree) returns the root tree, an object of type
+GtkTree (so, remember to cast it using GTK_WIDGET (Tree) if you want
+to use one of the gtk_widget_*() functions on it).
+
+Instead of directly accessing the children field of a GtkTree widget,
+it's probably best to cast it using GTK_CONTAINER (Tree), and pass it
+to the gtk_container_children() function. This creates a duplicate of
+the original list, so it's advisable to free it up using g_list_free()
+after you're done with it, or to iterate on it destructively, like
+this:
<tscreen><verb>
-GtkWidget *gtk_list_new( void );
+ children = gtk_container_children (GTK_CONTAINER (tree));
+ while (children) {
+ do_something_nice (GTK_TREE_ITEM (children->data));
+ children = g_list_remove_link (children, children);
+}
</verb></tscreen>
-Create a new GtkList object. The new widget is returned as a pointer
-to a GtkWidget object. NULL is returned on failure.
+The <tt>tree_owner</tt> field is defined only in subtrees, where it
+points to the GtkTreeItem widget which holds the tree in question.
+The <tt>level</tt> field indicates how deeply nested a particular tree
+is; root trees have level 0, and each successive level of subtrees has
+a level one greater than the parent level. This field is set only
+after a GtkTree widget is actually mapped (i.e. drawn on the screen).
+<sect2> Signals<label id="sec_GtkTree_Signals">
+<p>
<tscreen><verb>
-void gtk_list_insert_items( GtkList *list,
- GList *items,
- gint position );
+void selection_changed( GtkTree *tree );
</verb></tscreen>
-Insert list items into the list, starting at <tt/position/.
-<tt/items/ is a doubly linked list where each nodes data pointer is
-expected to point to a newly created GtkListItem. The GList nodes of
-<tt/items/ are taken over by the list.
+This signal will be emitted whenever the <tt>selection</tt> field of a
+GtkTree has changed. This happens when a child of the GtkTree is
+selected or deselected.
<tscreen><verb>
-void gtk_list_append_items( GtkList *list,
- GList *items);
+void select_child( GtkTree *tree,
+ GtkWidget *child );
</verb></tscreen>
-Insert list items just like gtk_list_insert_items() at the end of the
-list. The GList nodes of <tt/items/ are taken over by the list.
+This signal is emitted when a child of the GtkTree is about to get
+selected. This happens on calls to gtk_tree_select_item(),
+gtk_tree_select_child(), on <em>all</em> button presses and calls to
+gtk_tree_item_toggle() and gtk_item_toggle(). It may sometimes be
+indirectly triggered on other occasions where children get added to or
+removed from the GtkTree.
<tscreen><verb>
-void gtk_list_prepend_items( GtkList *list,
- GList *items);
+void unselect_child (GtkTree *tree,
+ GtkWidget *child);
</verb></tscreen>
-Insert list items just like gtk_list_insert_items() at the very
-beginning of the list. The GList nodes of <tt/items/ are taken over by
-the list.
+This signal is emitted when a child of the GtkTree is about to get
+deselected. As of GTK+ 1.0.4, this seems to only occur on calls to
+gtk_tree_unselect_item() or gtk_tree_unselect_child(), and perhaps on
+other occasions, but <em>not</em> when a button press deselects a
+child, nor on emission of the "toggle" signal by gtk_item_toggle().
+<sect2> Functions and Macros<label id="sec_GtkTree_Functions">
+<p>
<tscreen><verb>
-void gtk_list_remove_items( GtkList *list,
- GList *items);
+guint gtk_tree_get_type( void );
</verb></tscreen>
-Remove list items from the list. <tt/items/ is a doubly linked list
-where each nodes data pointer is expected to point to a direct child
-of list. It is the callers responsibility to make a call to
-g_list_free(items) afterwards. Also the caller has to destroy the list
-items himself.
+Returns the `GtkTree' type identifier.
<tscreen><verb>
-void gtk_list_clear_items( GtkList *list,
- gint start,
- gint end );
+GtkWidget* gtk_tree_new( void );
</verb></tscreen>
-Remove and destroy list items from the list. A widget is affected if
-its current position within the list is in the range specified by
-<tt/start/ and <tt/end/.
+Create a new GtkTree object. The new widget is returned as a pointer
+to a GtkWidget object. NULL is returned on failure.
<tscreen><verb>
-void gtk_list_select_item( GtkList *list,
+void gtk_tree_append( GtkTree *tree,
+ GtkWidget *tree_item );
+</verb></tscreen>
+
+Append a tree item to a GtkTree.
+
+<tscreen><verb>
+void gtk_tree_prepend( GtkTree *tree,
+ GtkWidget *tree_item );
+</verb></tscreen>
+
+Prepend a tree item to a GtkTree.
+
+<tscreen><verb>
+void gtk_tree_insert( GtkTree *tree,
+ GtkWidget *tree_item,
+ gint position );
+</verb></tscreen>
+
+Insert a tree item into a GtkTree at the position in the list
+specified by <tt>position.</tt>
+
+<tscreen><verb>
+void gtk_tree_remove_items( GtkTree *tree,
+ GList *items );
+</verb></tscreen>
+
+Remove a list of items (in the form of a GList *) from a GtkTree.
+Note that removing an item from a tree dereferences (and thus usually)
+destroys it <em>and</em> its subtree, if it has one, <em>and</em> all
+subtrees in that subtree. If you want to remove only one item, you
+can use gtk_container_remove().
+
+<tscreen><verb>
+void gtk_tree_clear_items( GtkTree *tree,
+ gint start,
+ gint end );
+</verb></tscreen>
+
+Remove the items from position <tt>start</tt> to position <tt>end</tt>
+from a GtkTree. The same warning about dereferencing applies here, as
+gtk_tree_clear_items() simply constructs a list and passes it to
+gtk_tree_remove_items().
+
+<tscreen><verb>
+void gtk_tree_select_item( GtkTree *tree,
gint item );
</verb></tscreen>
-Invoke the select_child signal for a list item specified through its
-current position within the list.
+Emits the "select_item" signal for the child at position
+<tt>item</tt>, thus selecting the child (unless you unselect it in a
+signal handler).
<tscreen><verb>
-void gtk_list_unselect_item( GtkList *list,
- gint item);
+void gtk_tree_unselect_item( GtkTree *tree,
+ gint item );
</verb></tscreen>
-Invoke the unselect_child signal for a list item specified through its
-current position within the list.
+Emits the "unselect_item" signal for the child at position
+<tt>item</tt>, thus unselecting the child.
<tscreen><verb>
-void gtk_list_select_child( GtkList *list,
- GtkWidget *child);
+void gtk_tree_select_child( GtkTree *tree,
+ GtkWidget *tree_item );
</verb></tscreen>
-Invoke the select_child signal for the specified child.
+Emits the "select_item" signal for the child <tt>tree_item</tt>, thus
+selecting it.
<tscreen><verb>
-void gtk_list_unselect_child( GtkList *list,
- GtkWidget *child);
+void gtk_tree_unselect_child( GtkTree *tree,
+ GtkWidget *tree_item );
</verb></tscreen>
-Invoke the unselect_child signal for the specified child.
+Emits the "unselect_item" signal for the child <tt>tree_item</tt>,
+thus unselecting it.
<tscreen><verb>
-gint gtk_list_child_position( GtkList *list,
- GtkWidget *child);
+gint gtk_tree_child_position( GtkTree *tree,
+ GtkWidget *child );
</verb></tscreen>
-Return the position of <tt/child/ within the list. "-1" is returned on
-failure.
+Returns the position in the tree of <tt>child</tt>, unless
+<tt>child</tt> is not in the tree, in which case it returns -1.
<tscreen><verb>
-void gtk_list_set_selection_mode( GtkList *list,
- GtkSelectionMode mode );
+void gtk_tree_set_selection_mode( GtkTree *tree,
+ GtkSelectionMode mode );
</verb></tscreen>
-Set the selection mode MODE which can be of GTK_SELECTION_SINGLE,
-GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE or
-GTK_SELECTION_EXTENDED.
+Sets the selection mode, which can be one of GTK_SELECTION_SINGLE (the
+default), GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE, or
+GTK_SELECTION_EXTENDED. This is only defined for root trees, which
+makes sense, since the root tree "owns" the selection. Setting it for
+subtrees has no effect at all; the value is simply ignored.
<tscreen><verb>
-GtkList *GTK_LIST( gpointer obj );
+void gtk_tree_set_view_mode( GtkTree *tree,
+ GtkTreeViewMode mode );
</verb></tscreen>
-Cast a generic pointer to `GtkList *'. *Note Standard Macros::, for
-more info.
+Sets the "view mode", which can be either GTK_TREE_VIEW_LINE (the
+default) or GTK_TREE_VIEW_ITEM. The view mode propagates from a tree
+to its subtrees, and can't be set exclusively to a subtree (this is
+not exactly true - see the example code comments).
+
+The term "view mode" is rather ambiguous - basically, it controls the
+way the highlight is drawn when one of a tree's children is selected.
+If it's GTK_TREE_VIEW_LINE, the entire GtkTreeItem widget is
+highlighted, while for GTK_TREE_VIEW_ITEM, only the child widget
+(i.e. usually the label) is highlighted.
<tscreen><verb>
-GtkListClass *GTK_LIST_CLASS( gpointer class);
+void gtk_tree_set_view_lines( GtkTree *tree,
+ guint flag );
</verb></tscreen>
-Cast a generic pointer to `GtkListClass*'. *Note Standard Macros::,
-for more info.
+Controls whether connecting lines between tree items are drawn.
+<tt>flag</tt> is either TRUE, in which case they are, or FALSE, in
+which case they aren't.
<tscreen><verb>
-gint GTK_IS_LIST( gpointer obj);
+GtkTree *GTK_TREE (gpointer obj);
</verb></tscreen>
-Determine if a generic pointer refers to a `GtkList' object. *Note
-Standard Macros::, for more info.
+Cast a generic pointer to `GtkTree *'.
-<!-- ----------------------------------------------------------------- -->
-<sect1> Example
+<tscreen><verb>
+GtkTreeClass *GTK_TREE_CLASS (gpointer class);
+</verb></tscreen>
+
+Cast a generic pointer to `GtkTreeClass*'.
+
+<tscreen><verb>
+gint GTK_IS_TREE (gpointer obj);
+</verb></tscreen>
+
+Determine if a generic pointer refers to a `GtkTree' object.
+
+<tscreen><verb>
+gint GTK_IS_ROOT_TREE (gpointer obj)
+</verb></tscreen>
+
+Determine if a generic pointer refers to a `GtkTree' object
+<em>and</em> is a root tree. Though this will accept any pointer, the
+results of passing it a pointer that does not refer to a GtkTree are
+undefined and possibly harmful.
+
+<tscreen><verb>
+GtkTree *GTK_TREE_ROOT_TREE (gpointer obj)
+</verb></tscreen>
+
+Return the root tree of a pointer to a `GtkTree' object. The above
+warning applies.
+
+<tscreen><verb>
+GList *GTK_TREE_SELECTION( gpointer obj)
+</verb></tscreen>
+
+Return the selection list of the root tree of a `GtkTree' object. The
+above warning applies here, too.
+
+<sect1> Tree Item Widget<label id="sec_Tree_Item_Widget">
<p>
-Following is an example program that will print out the changes of the
-selection of a GtkList, and lets you "arrest" list items into a prison
-by selecting them with the rightmost mouse button.
+The GtkTreeItem widget, like GtkListItem, is derived from GtkItem,
+which in turn is derived from GtkBin. Therefore, the item itself is a
+generic container holding exactly one child widget, which can be of
+any type. The GtkTreeItem widget has a number of extra fields, but
+the only one we need be concerned with is the <tt>subtree</tt> field.
+
+The definition for the GtkTreeItem struct looks like this:
<tscreen><verb>
-/* example-start list list.c */
+struct _GtkTreeItem
+{
+ GtkItem item;
-/* Include the gtk+ header files
- * Include stdio.h, we need that for the printf() function
- */
-#include <gtk/gtk.h>
-#include <stdio.h>
+ GtkWidget *subtree;
+ GtkWidget *pixmaps_box;
+ GtkWidget *plus_pix_widget, *minus_pix_widget;
-/* This is our data identification string to store
- * data in list items
- */
-const gchar *list_item_data_key="list_item_data";
+ GList *pixmaps; /* pixmap node for this items color depth */
+ guint expanded : 1;
+};
+</verb></tscreen>
-/* prototypes for signal handler that we are going to connect
- * to the GtkList widget
- */
-static void sigh_print_selection( GtkWidget *gtklist,
- gpointer func_data);
+The <tt>pixmaps_box</tt> field is a GtkEventBox which catches clicks
+on the plus/minus symbol which controls expansion and collapsing. The
+<tt>pixmaps</tt> field points to an internal data structure. Since
+you can always obtain the subtree of a GtkTreeItem in a (relatively)
+type-safe manner with the GTK_TREE_ITEM_SUBTREE (Item) macro, it's
+probably advisable never to touch the insides of a GtkTreeItem unless
+you <em>really</em> know what you're doing.
-static void sigh_button_event( GtkWidget *gtklist,
- GdkEventButton *event,
- GtkWidget *frame );
+Since it is directly derived from a GtkItem it can be treated as such
+by using the GTK_ITEM (TreeItem) macro. A GtkTreeItem usually holds a
+label, so the convenience function gtk_list_item_new_with_label() is
+provided. The same effect can be achieved using code like the
+following, which is actually copied verbatim from
+gtk_tree_item_new_with_label():
+<tscreen><verb>
+tree_item = gtk_tree_item_new ();
+label_widget = gtk_label_new (label);
+gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
-/* Main function to set up the user interface */
+gtk_container_add (GTK_CONTAINER (tree_item), label_widget);
+gtk_widget_show (label_widget);
+</verb></tscreen>
-gint main (int argc,
- gchar *argv[])
-{
- GtkWidget *separator;
- GtkWidget *window;
- GtkWidget *vbox;
- GtkWidget *scrolled_window;
- GtkWidget *frame;
- GtkWidget *gtklist;
- GtkWidget *button;
- GtkWidget *list_item;
- GList *dlist;
- guint i;
- gchar buffer[64];
-
-
- /* Initialize gtk+ (and subsequently gdk) */
-
- gtk_init(&argc, &argv);
-
-
- /* Create a window to put all the widgets in
- * connect gtk_main_quit() to the "destroy" event of
- * the window to handle window manager close-window-events
- */
- window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_window_set_title(GTK_WINDOW(window), "GtkList Example");
- gtk_signal_connect(GTK_OBJECT(window),
- "destroy",
- GTK_SIGNAL_FUNC(gtk_main_quit),
- NULL);
-
-
- /* Inside the window we need a box to arrange the widgets
- * vertically */
- vbox=gtk_vbox_new(FALSE, 5);
- gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
- gtk_container_add(GTK_CONTAINER(window), vbox);
- gtk_widget_show(vbox);
-
- /* This is the scrolled window to put the GtkList widget inside */
- scrolled_window=gtk_scrolled_window_new(NULL, NULL);
- gtk_widget_set_usize(scrolled_window, 250, 150);
- gtk_container_add(GTK_CONTAINER(vbox), scrolled_window);
- gtk_widget_show(scrolled_window);
-
- /* Create the GtkList widget.
- * Connect the sigh_print_selection() signal handler
- * function to the "selection_changed" signal of the GtkList
- * to print out the selected items each time the selection
- * has changed */
- gtklist=gtk_list_new();
- gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window),
- gtklist);
- gtk_widget_show(gtklist);
- gtk_signal_connect(GTK_OBJECT(gtklist),
- "selection_changed",
- GTK_SIGNAL_FUNC(sigh_print_selection),
- NULL);
-
- /* We create a "Prison" to put a list item in ;) */
- frame=gtk_frame_new("Prison");
- gtk_widget_set_usize(frame, 200, 50);
- gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
- gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
- gtk_container_add(GTK_CONTAINER(vbox), frame);
- gtk_widget_show(frame);
-
- /* Connect the sigh_button_event() signal handler to the GtkList
- * which will handle the "arresting" of list items
- */
- gtk_signal_connect(GTK_OBJECT(gtklist),
- "button_release_event",
- GTK_SIGNAL_FUNC(sigh_button_event),
- frame);
-
- /* Create a separator */
- separator=gtk_hseparator_new();
- gtk_container_add(GTK_CONTAINER(vbox), separator);
- gtk_widget_show(separator);
-
- /* Finally create a button and connect it's "clicked" signal
- * to the destruction of the window */
- button=gtk_button_new_with_label("Close");
- gtk_container_add(GTK_CONTAINER(vbox), button);
- gtk_widget_show(button);
- gtk_signal_connect_object(GTK_OBJECT(button),
- "clicked",
- GTK_SIGNAL_FUNC(gtk_widget_destroy),
- GTK_OBJECT(window));
-
-
- /* Now we create 5 list items, each having it's own
- * label and add them to the GtkList using gtk_container_add()
- * Also we query the text string from the label and
- * associate it with the list_item_data_key for each list item
- */
- for (i=0; i<5; i++) {
- GtkWidget *label;
- gchar *string;
-
- sprintf(buffer, "ListItemContainer with Label #%d", i);
- label=gtk_label_new(buffer);
- list_item=gtk_list_item_new();
- gtk_container_add(GTK_CONTAINER(list_item), label);
- gtk_widget_show(label);
- gtk_container_add(GTK_CONTAINER(gtklist), list_item);
- gtk_widget_show(list_item);
- gtk_label_get(GTK_LABEL(label), &string);
- gtk_object_set_data(GTK_OBJECT(list_item),
- list_item_data_key,
- string);
- }
- /* Here, we are creating another 5 labels, this time
- * we use gtk_list_item_new_with_label() for the creation
- * we can't query the text string from the label because
- * we don't have the labels pointer and therefore
- * we just associate the list_item_data_key of each
- * list item with the same text string.
- * For adding of the list items we put them all into a doubly
- * linked list (GList), and then add them by a single call to
- * gtk_list_append_items().
- * Because we use g_list_prepend() to put the items into the
- * doubly linked list, their order will be descending (instead
- * of ascending when using g_list_append())
- */
- dlist=NULL;
- for (; i<10; i++) {
- sprintf(buffer, "List Item with Label %d", i);
- list_item=gtk_list_item_new_with_label(buffer);
- dlist=g_list_prepend(dlist, list_item);
- gtk_widget_show(list_item);
- gtk_object_set_data(GTK_OBJECT(list_item),
- list_item_data_key,
- "ListItem with integrated Label");
- }
- gtk_list_append_items(GTK_LIST(gtklist), dlist);
-
- /* Finally we want to see the window, don't we? ;) */
- gtk_widget_show(window);
-
- /* Fire up the main event loop of gtk */
- gtk_main();
-
- /* We get here after gtk_main_quit() has been called which
- * happens if the main window gets destroyed
- */
- return(0);
-}
-
-/* This is the signal handler that got connected to button
- * press/release events of the GtkList
- */
-void sigh_button_event( GtkWidget *gtklist,
- GdkEventButton *event,
- GtkWidget *frame )
-{
- /* We only do something if the third (rightmost mouse button
- * was released
- */
- if (event->type==GDK_BUTTON_RELEASE &&
- event->button==3) {
- GList *dlist, *free_list;
- GtkWidget *new_prisoner;
-
- /* Fetch the currently selected list item which
- * will be our next prisoner ;)
- */
- dlist=GTK_LIST(gtklist)->selection;
- if (dlist)
- new_prisoner=GTK_WIDGET(dlist->data);
- else
- new_prisoner=NULL;
-
- /* Look for already imprisoned list items, we
- * will put them back into the list.
- * Remember to free the doubly linked list that
- * gtk_container_children() returns
- */
- dlist=gtk_container_children(GTK_CONTAINER(frame));
- free_list=dlist;
- while (dlist) {
- GtkWidget *list_item;
-
- list_item=dlist->data;
-
- gtk_widget_reparent(list_item, gtklist);
-
- dlist=dlist->next;
- }
- g_list_free(free_list);
-
- /* If we have a new prisoner, remove him from the
- * GtkList and put him into the frame "Prison".
- * We need to unselect the item first.
- */
- if (new_prisoner) {
- GList static_dlist;
-
- static_dlist.data=new_prisoner;
- static_dlist.next=NULL;
- static_dlist.prev=NULL;
-
- gtk_list_unselect_child(GTK_LIST(gtklist),
- new_prisoner);
- gtk_widget_reparent(new_prisoner, frame);
- }
- }
-}
-
-/* This is the signal handler that gets called if GtkList
- * emits the "selection_changed" signal
- */
-void sigh_print_selection( GtkWidget *gtklist,
- gpointer func_data)
-{
- GList *dlist;
-
- /* Fetch the doubly linked list of selected items
- * of the GtkList, remember to treat this as read-only!
- */
- dlist=GTK_LIST(gtklist)->selection;
-
- /* If there are no selected items there is nothing more
- * to do than just telling the user so
- */
- if (!dlist) {
- g_print("Selection cleared\n");
- return;
- }
- /* Ok, we got a selection and so we print it
- */
- g_print("The selection is a ");
-
- /* Get the list item from the doubly linked list
- * and then query the data associated with list_item_data_key.
- * We then just print it */
- while (dlist) {
- GtkObject *list_item;
- gchar *item_data_string;
-
- list_item=GTK_OBJECT(dlist->data);
- item_data_string=gtk_object_get_data(list_item,
- list_item_data_key);
- g_print("%s ", item_data_string);
-
- dlist=dlist->next;
- }
- g_print("\n");
-}
-/* example-end */
-</verb></tscreen>
-
-<!-- ----------------------------------------------------------------- -->
-<sect1> List Item Widget
-<p>
-The GtkListItem widget is designed to act as a container holding up to
-one child, providing functions for selection/deselection just like the
-GtkList widget requires them for its children.
-
-A GtkListItem has its own window to receive events and has its own
-background color which is usually white.
-
-As it is directly derived from a GtkItem it can be treated as such by
-using the GTK_ITEM(ListItem) macro, see the GtkItem widget for more on
-this. Usually a GtkListItem just holds a label to identify e.g. a
-filename within a GtkList -- therefore the convenience function
-gtk_list_item_new_with_label() is provided. The same effect can be
-achieved by creating a GtkLabel on its own, setting its alignment to
-xalign=0 and yalign=0.5 with a subsequent container addition to the
-GtkListItem.
-
-As one is not forced to add a GtkLabel to a GtkListItem, you could
-also add a GtkVBox or a GtkArrow etc. to the GtkListItem.
-
-<!-- ----------------------------------------------------------------- -->
-<sect1> Signals
-<p>
-A GtkListItem does not create new signals on its own, but inherits
-the signals of a GtkItem. *Note GtkItem::, for more info.
-
-<!-- ----------------------------------------------------------------- -->
-<sect1> Functions
-<p>
-<tscreen><verb>
-guint gtk_list_item_get_type( void );
-</verb></tscreen>
-
-Returns the `GtkListItem' type identifier.
-
-<tscreen><verb>
-GtkWidget *gtk_list_item_new( void );
-</verb></tscreen>
-
-Create a new GtkListItem object. The new widget is returned as a
-pointer to a GtkWidget object. NULL is returned on failure.
-
-<tscreen><verb>
-GtkWidget *gtk_list_item_new_with_label( gchar *label );
-</verb></tscreen>
-
-Create a new GtkListItem object, having a single GtkLabel as the sole
-child. The new widget is returned as a pointer to a GtkWidget
-object. NULL is returned on failure.
-
-<tscreen><verb>
-void gtk_list_item_select( GtkListItem *list_item );
-</verb></tscreen>
-
-This function is basically a wrapper around a call to gtk_item_select
-(GTK_ITEM (list_item)) which will emit the select signal. *Note
-GtkItem::, for more info.
-
-<tscreen><verb>
-void gtk_list_item_deselect( GtkListItem *list_item );
-</verb></tscreen>
-
-This function is basically a wrapper around a call to
-gtk_item_deselect (GTK_ITEM (list_item)) which will emit the deselect
-signal. *Note GtkItem::, for more info.
-
-<tscreen><verb>
-GtkListItem *GTK_LIST_ITEM( gpointer obj );
-</verb></tscreen>
-
-Cast a generic pointer to `GtkListItem*'. *Note Standard Macros::, for
-more info.
-
-<tscreen><verb>
-GtkListItemClass *GTK_LIST_ITEM_CLASS( gpointer class );
-</verb></tscreen>
-
-Cast a generic pointer to GtkListItemClass*. *Note Standard Macros::,
-for more info.
-
-<tscreen><verb>
-gint GTK_IS_LIST_ITEM( gpointer obj );
-</verb></tscreen>
-
-Determine if a generic pointer refers to a `GtkListItem' object.
-*Note Standard Macros::, for more info.
-
-<!-- ----------------------------------------------------------------- -->
-<sect1> Example
-<p>
-Please see the GtkList example on this, which covers the usage of a
-GtkListItem as well.
-
-<!-- ***************************************************************** -->
-<sect> Tree Widget<label id="sec_Tree_Widgets">
-<!-- ***************************************************************** -->
-<p>
-The purpose of tree widgets is to display hierarchically-organized
-data. The GtkTree widget itself is a vertical container for widgets of
-type GtkTreeItem. GtkTree itself is not terribly different from
-GtkList - both are derived directly from GtkContainer, and the
-GtkContainer methods work in the same way on GtkTree widgets as on
-GtkList widgets. The difference is that GtkTree widgets can be nested
-within other GtkTree widgets. We'll see how to do this shortly.
-
-The GtkTree widget has its own window, and defaults to a white
-background, as does GtkList. Also, most of the GtkTree methods work in
-the same way as the corresponding GtkList ones. However, GtkTree is
-not derived from GtkList, so you cannot use them interchangeably.
-
-<sect1> Creating a Tree
-<p>
-A GtkTree is created in the usual way, using:
-
-<tscreen><verb>
-GtkWidget* gtk_tree_new( void );
-</verb></tscreen>
-
-Like the GtkList widget, a GtkTree will simply keep growing as more
-items are added to it, as well as when subtrees are expanded. For
-this reason, they are almost always packed into a
-GtkScrolledWindow. You might want to use gtk_widget_set_usize() on the
-scrolled window to ensure that it is big enough to see the tree's
-items, as the default size for GtkScrolledWindow is quite small.
-
-Now that you have a tree, you'll probably want to add some items to
-it. <ref id="sec_Tree_Item_Widget" name="The Tree Item Widget"> below
-explains the gory details of GtkTreeItem. For now, it'll suffice to
-create one, using:
-
-<tscreen><verb>
-GtkWidget* gtk_tree_item_new_with_label( gchar *label );
-</verb></tscreen>
-
-You can then add it to the tree using one of the following (see
-<ref id="sec_GtkTree_Functions" name="Functions and Macros">
-below for more options):
-
-<tscreen><verb>
-void gtk_tree_append( GtkTree *tree,
- GtkWidget *tree_item );
-
-void gtk_tree_prepend( GtkTree *tree,
- GtkWidget *tree_item );
-</verb></tscreen>
-
-Note that you must add items to a GtkTree one at a time - there is no
-equivalent to gtk_list_*_items().
-
-<!-- ----------------------------------------------------------------- -->
-<sect1> Adding a Subtree
-<p>
-A subtree is created like any other GtkTree widget. A subtree is added
-to another tree beneath a tree item, using:
-
-<tscreen><verb>
-void gtk_tree_item_set_subtree( GtkTreeItem *tree_item,
- GtkWidget *subtree );
-</verb></tscreen>
-
-You do not need to call gtk_widget_show() on a subtree before or after
-adding it to a GtkTreeItem. However, you <em>must</em> have added the
-GtkTreeItem in question to a parent tree before calling
-gtk_tree_item_set_subtree(). This is because, technically, the parent
-of the subtree is <em>not</em> the GtkTreeItem which "owns" it, but
-rather the GtkTree which holds that GtkTreeItem.
-
-When you add a subtree to a GtkTreeItem, a plus or minus sign appears
-beside it, which the user can click on to "expand" or "collapse" it,
-meaning, to show or hide its subtree. GtkTreeItems are collapsed by
-default. Note that when you collapse a GtkTreeItem, any selected
-items in its subtree remain selected, which may not be what the user
-expects.
-
-<!-- ----------------------------------------------------------------- -->
-<sect1> Handling the Selection List
-<p>
-As with GtkList, the GtkTree type has a <tt>selection</tt> field, and
-it is possible to control the behaviour of the tree (somewhat) by
-setting the selection type using:
-
-<tscreen><verb>
-void gtk_tree_set_selection_mode( GtkTree *tree,
- GtkSelectionMode mode );
-</verb></tscreen>
-
-The semantics associated with the various selection modes are
-described in the section on the GtkList widget. As with the GtkList
-widget, the "select_child", "unselect_child" (not really - see <ref
-id="sec_GtkTree_Signals" name="Signals"> below for an explanation),
-and "selection_changed" signals are emitted when list items are
-selected or unselected. However, in order to take advantage of these
-signals, you need to know <em>which</em> GtkTree widget they will be
-emitted by, and where to find the list of selected items.
-
-This is a source of potential confusion. The best way to explain this
-is that though all GtkTree widgets are created equal, some are more
-equal than others. All GtkTree widgets have their own X window, and
-can therefore receive events such as mouse clicks (if their
-GtkTreeItems or their children don't catch them first!). However, to
-make GTK_SELECTION_SINGLE and GTK_SELECTION_BROWSE selection types
-behave in a sane manner, the list of selected items is specific to the
-topmost GtkTree widget in a hierarchy, known as the "root tree".
-
-Thus, accessing the <tt>selection</tt>field directly in an arbitrary
-GtkTree widget is not a good idea unless you <em>know</em> it's the
-root tree. Instead, use the GTK_TREE_SELECTION (Tree) macro, which
-gives the root tree's selection list as a GList pointer. Of course,
-this list can include items that are not in the subtree in question if
-the selection type is GTK_SELECTION_MULTIPLE.
-
-Finally, the "select_child" (and "unselect_child", in theory) signals
-are emitted by all trees, but the "selection_changed" signal is only
-emitted by the root tree. Consequently, if you want to handle the
-"select_child" signal for a tree and all its subtrees, you will have
-to call gtk_signal_connect() for every subtree.
-
-<sect1> Tree Widget Internals
-<p>
-The GtkTree's struct definition looks like this:
-
-<tscreen><verb>
-struct _GtkTree
-{
- GtkContainer container;
-
- GList *children;
-
- GtkTree* root_tree; /* owner of selection list */
- GtkWidget* tree_owner;
- GList *selection;
- guint level;
- guint indent_value;
- guint current_indent;
- guint selection_mode : 2;
- guint view_mode : 1;
- guint view_line : 1;
-};
-</verb></tscreen>
-
-The perils associated with accessing the <tt>selection</tt> field
-directly have already been mentioned. The other important fields of
-the struct can also be accessed with handy macros or class functions.
-GTK_TREE_IS_ROOT_TREE (Tree) returns a boolean value which indicates
-whether a tree is the root tree in a GtkTree hierarchy, while
-GTK_TREE_ROOT_TREE (Tree) returns the root tree, an object of type
-GtkTree (so, remember to cast it using GTK_WIDGET (Tree) if you want
-to use one of the gtk_widget_*() functions on it).
-
-Instead of directly accessing the children field of a GtkTree widget,
-it's probably best to cast it using GTK_CONTAINER (Tree), and pass it
-to the gtk_container_children() function. This creates a duplicate of
-the original list, so it's advisable to free it up using g_list_free()
-after you're done with it, or to iterate on it destructively, like
-this:
-
-<tscreen><verb>
- children = gtk_container_children (GTK_CONTAINER (tree));
- while (children) {
- do_something_nice (GTK_TREE_ITEM (children->data));
- children = g_list_remove_link (children, children);
-}
-</verb></tscreen>
-
-The <tt>tree_owner</tt> field is defined only in subtrees, where it
-points to the GtkTreeItem widget which holds the tree in question.
-The <tt>level</tt> field indicates how deeply nested a particular tree
-is; root trees have level 0, and each successive level of subtrees has
-a level one greater than the parent level. This field is set only
-after a GtkTree widget is actually mapped (i.e. drawn on the screen).
-
-<sect2> Signals<label id="sec_GtkTree_Signals">
-<p>
-<tscreen><verb>
-void selection_changed( GtkTree *tree );
-</verb></tscreen>
-
-This signal will be emitted whenever the <tt>selection</tt> field of a
-GtkTree has changed. This happens when a child of the GtkTree is
-selected or deselected.
-
-<tscreen><verb>
-void select_child( GtkTree *tree,
- GtkWidget *child );
-</verb></tscreen>
-
-This signal is emitted when a child of the GtkTree is about to get
-selected. This happens on calls to gtk_tree_select_item(),
-gtk_tree_select_child(), on <em>all</em> button presses and calls to
-gtk_tree_item_toggle() and gtk_item_toggle(). It may sometimes be
-indirectly triggered on other occasions where children get added to or
-removed from the GtkTree.
-
-<tscreen><verb>
-void unselect_child (GtkTree *tree,
- GtkWidget *child);
-</verb></tscreen>
-
-This signal is emitted when a child of the GtkTree is about to get
-deselected. As of GTK+ 1.0.4, this seems to only occur on calls to
-gtk_tree_unselect_item() or gtk_tree_unselect_child(), and perhaps on
-other occasions, but <em>not</em> when a button press deselects a
-child, nor on emission of the "toggle" signal by gtk_item_toggle().
-
-<sect2> Functions and Macros<label id="sec_GtkTree_Functions">
-<p>
-<tscreen><verb>
-guint gtk_tree_get_type( void );
-</verb></tscreen>
-
-Returns the `GtkTree' type identifier.
-
-<tscreen><verb>
-GtkWidget* gtk_tree_new( void );
-</verb></tscreen>
-
-Create a new GtkTree object. The new widget is returned as a pointer
-to a GtkWidget object. NULL is returned on failure.
-
-<tscreen><verb>
-void gtk_tree_append( GtkTree *tree,
- GtkWidget *tree_item );
-</verb></tscreen>
-
-Append a tree item to a GtkTree.
-
-<tscreen><verb>
-void gtk_tree_prepend( GtkTree *tree,
- GtkWidget *tree_item );
-</verb></tscreen>
-
-Prepend a tree item to a GtkTree.
-
-<tscreen><verb>
-void gtk_tree_insert( GtkTree *tree,
- GtkWidget *tree_item,
- gint position );
-</verb></tscreen>
-
-Insert a tree item into a GtkTree at the position in the list
-specified by <tt>position.</tt>
-
-<tscreen><verb>
-void gtk_tree_remove_items( GtkTree *tree,
- GList *items );
-</verb></tscreen>
-
-Remove a list of items (in the form of a GList *) from a GtkTree.
-Note that removing an item from a tree dereferences (and thus usually)
-destroys it <em>and</em> its subtree, if it has one, <em>and</em> all
-subtrees in that subtree. If you want to remove only one item, you
-can use gtk_container_remove().
-
-<tscreen><verb>
-void gtk_tree_clear_items( GtkTree *tree,
- gint start,
- gint end );
-</verb></tscreen>
-
-Remove the items from position <tt>start</tt> to position <tt>end</tt>
-from a GtkTree. The same warning about dereferencing applies here, as
-gtk_tree_clear_items() simply constructs a list and passes it to
-gtk_tree_remove_items().
-
-<tscreen><verb>
-void gtk_tree_select_item( GtkTree *tree,
- gint item );
-</verb></tscreen>
-
-Emits the "select_item" signal for the child at position
-<tt>item</tt>, thus selecting the child (unless you unselect it in a
-signal handler).
-
-<tscreen><verb>
-void gtk_tree_unselect_item( GtkTree *tree,
- gint item );
-</verb></tscreen>
-
-Emits the "unselect_item" signal for the child at position
-<tt>item</tt>, thus unselecting the child.
-
-<tscreen><verb>
-void gtk_tree_select_child( GtkTree *tree,
- GtkWidget *tree_item );
-</verb></tscreen>
-
-Emits the "select_item" signal for the child <tt>tree_item</tt>, thus
-selecting it.
-
-<tscreen><verb>
-void gtk_tree_unselect_child( GtkTree *tree,
- GtkWidget *tree_item );
-</verb></tscreen>
-
-Emits the "unselect_item" signal for the child <tt>tree_item</tt>,
-thus unselecting it.
-
-<tscreen><verb>
-gint gtk_tree_child_position( GtkTree *tree,
- GtkWidget *child );
-</verb></tscreen>
-
-Returns the position in the tree of <tt>child</tt>, unless
-<tt>child</tt> is not in the tree, in which case it returns -1.
-
-<tscreen><verb>
-void gtk_tree_set_selection_mode( GtkTree *tree,
- GtkSelectionMode mode );
-</verb></tscreen>
-
-Sets the selection mode, which can be one of GTK_SELECTION_SINGLE (the
-default), GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE, or
-GTK_SELECTION_EXTENDED. This is only defined for root trees, which
-makes sense, since the root tree "owns" the selection. Setting it for
-subtrees has no effect at all; the value is simply ignored.
-
-<tscreen><verb>
-void gtk_tree_set_view_mode( GtkTree *tree,
- GtkTreeViewMode mode );
-</verb></tscreen>
-
-Sets the "view mode", which can be either GTK_TREE_VIEW_LINE (the
-default) or GTK_TREE_VIEW_ITEM. The view mode propagates from a tree
-to its subtrees, and can't be set exclusively to a subtree (this is
-not exactly true - see the example code comments).
-
-The term "view mode" is rather ambiguous - basically, it controls the
-way the highlight is drawn when one of a tree's children is selected.
-If it's GTK_TREE_VIEW_LINE, the entire GtkTreeItem widget is
-highlighted, while for GTK_TREE_VIEW_ITEM, only the child widget
-(i.e. usually the label) is highlighted.
-
-<tscreen><verb>
-void gtk_tree_set_view_lines( GtkTree *tree,
- guint flag );
-</verb></tscreen>
-
-Controls whether connecting lines between tree items are drawn.
-<tt>flag</tt> is either TRUE, in which case they are, or FALSE, in
-which case they aren't.
-
-<tscreen><verb>
-GtkTree *GTK_TREE (gpointer obj);
-</verb></tscreen>
-
-Cast a generic pointer to `GtkTree *'.
-
-<tscreen><verb>
-GtkTreeClass *GTK_TREE_CLASS (gpointer class);
-</verb></tscreen>
-
-Cast a generic pointer to `GtkTreeClass*'.
-
-<tscreen><verb>
-gint GTK_IS_TREE (gpointer obj);
-</verb></tscreen>
-
-Determine if a generic pointer refers to a `GtkTree' object.
-
-<tscreen><verb>
-gint GTK_IS_ROOT_TREE (gpointer obj)
-</verb></tscreen>
-
-Determine if a generic pointer refers to a `GtkTree' object
-<em>and</em> is a root tree. Though this will accept any pointer, the
-results of passing it a pointer that does not refer to a GtkTree are
-undefined and possibly harmful.
-
-<tscreen><verb>
-GtkTree *GTK_TREE_ROOT_TREE (gpointer obj)
-</verb></tscreen>
-
-Return the root tree of a pointer to a `GtkTree' object. The above
-warning applies.
-
-<tscreen><verb>
-GList *GTK_TREE_SELECTION( gpointer obj)
-</verb></tscreen>
-
-Return the selection list of the root tree of a `GtkTree' object. The
-above warning applies here, too.
-
-<sect1> Tree Item Widget<label id="sec_Tree_Item_Widget">
-<p>
-The GtkTreeItem widget, like GtkListItem, is derived from GtkItem,
-which in turn is derived from GtkBin. Therefore, the item itself is a
-generic container holding exactly one child widget, which can be of
-any type. The GtkTreeItem widget has a number of extra fields, but
-the only one we need be concerned with is the <tt>subtree</tt> field.
-
-The definition for the GtkTreeItem struct looks like this:
-
-<tscreen><verb>
-struct _GtkTreeItem
-{
- GtkItem item;
-
- GtkWidget *subtree;
- GtkWidget *pixmaps_box;
- GtkWidget *plus_pix_widget, *minus_pix_widget;
-
- GList *pixmaps; /* pixmap node for this items color depth */
-
- guint expanded : 1;
-};
-</verb></tscreen>
-
-The <tt>pixmaps_box</tt> field is a GtkEventBox which catches clicks
-on the plus/minus symbol which controls expansion and collapsing. The
-<tt>pixmaps</tt> field points to an internal data structure. Since
-you can always obtain the subtree of a GtkTreeItem in a (relatively)
-type-safe manner with the GTK_TREE_ITEM_SUBTREE (Item) macro, it's
-probably advisable never to touch the insides of a GtkTreeItem unless
-you <em>really</em> know what you're doing.
-
-Since it is directly derived from a GtkItem it can be treated as such
-by using the GTK_ITEM (TreeItem) macro. A GtkTreeItem usually holds a
-label, so the convenience function gtk_list_item_new_with_label() is
-provided. The same effect can be achieved using code like the
-following, which is actually copied verbatim from
-gtk_tree_item_new_with_label():
-
-<tscreen><verb>
-tree_item = gtk_tree_item_new ();
-label_widget = gtk_label_new (label);
-gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.5);
-
-gtk_container_add (GTK_CONTAINER (tree_item), label_widget);
-gtk_widget_show (label_widget);
-</verb></tscreen>
-
-As one is not forced to add a GtkLabel to a GtkTreeItem, you could
-also add a GtkHBox or a GtkArrow, or even a GtkNotebook (though your
-app will likely be quite unpopular in this case) to the GtkTreeItem.
+As one is not forced to add a GtkLabel to a GtkTreeItem, you could
+also add a GtkHBox or a GtkArrow, or even a GtkNotebook (though your
+app will likely be quite unpopular in this case) to the GtkTreeItem.
If you remove all the items from a subtree, it will be destroyed and
unparented, unless you reference it beforehand, and the GtkTreeItem
<sect1> Drawing Area
<p>
<!-- ----------------------------------------------------------------- -->
-<sect1> Fixed Container
-<p>
-<!-- ----------------------------------------------------------------- -->
-<sect1> Frame
-<p>
-<!-- ----------------------------------------------------------------- -->
<sect1> Font Selection Dialog
<p>
<!-- ----------------------------------------------------------------- -->
data types, which allows it to be cast to a specific
event data type within a signal handler.
-<!-- Just a big list for now, needs expanding upon - TRG -->
-So, the event data types are defined as follows:
+<!-- Just a big list for now, needs expanding upon - TRG -->
+So, the event data types are defined as follows:
+
+<tscreen><verb>
+struct _GdkEventAny
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+};
+
+struct _GdkEventExpose
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ GdkRectangle area;
+ gint count; /* If non-zero, how many more events follow. */
+};
+
+struct _GdkEventNoExpose
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ /* XXX: does anyone need the X major_code or minor_code fields? */
+};
+
+struct _GdkEventVisibility
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ GdkVisibilityState state;
+};
+
+struct _GdkEventMotion
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ guint32 time;
+ gdouble x;
+ gdouble y;
+ gdouble pressure;
+ gdouble xtilt;
+ gdouble ytilt;
+ guint state;
+ gint16 is_hint;
+ GdkInputSource source;
+ guint32 deviceid;
+ gdouble x_root, y_root;
+};
+
+struct _GdkEventButton
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ guint32 time;
+ gdouble x;
+ gdouble y;
+ gdouble pressure;
+ gdouble xtilt;
+ gdouble ytilt;
+ guint state;
+ guint button;
+ GdkInputSource source;
+ guint32 deviceid;
+ gdouble x_root, y_root;
+};
+
+struct _GdkEventKey
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ guint32 time;
+ guint state;
+ guint keyval;
+ gint length;
+ gchar *string;
+};
+
+struct _GdkEventCrossing
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ GdkWindow *subwindow;
+ GdkNotifyType detail;
+};
+
+struct _GdkEventFocus
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ gint16 in;
+};
+
+struct _GdkEventConfigure
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ gint16 x, y;
+ gint16 width;
+ gint16 height;
+};
+
+struct _GdkEventProperty
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ GdkAtom atom;
+ guint32 time;
+ guint state;
+};
+
+struct _GdkEventSelection
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ GdkAtom selection;
+ GdkAtom target;
+ GdkAtom property;
+ guint32 requestor;
+ guint32 time;
+};
+
+/* This event type will be used pretty rarely. It only is important
+ for XInput aware programs that are drawing their own cursor */
+
+struct _GdkEventProximity
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ guint32 time;
+ GdkInputSource source;
+ guint32 deviceid;
+};
+
+struct _GdkEventDragRequest
+{
+ GdkEventType type;
+ GdkWindow *window;
+ gint8 send_event;
+ guint32 requestor;
+ union {
+ struct {
+ guint protocol_version:4;
+ guint sendreply:1;
+ guint willaccept:1;
+ guint delete_data:1; /* Do *not* delete if link is sent, only
+ if data is sent */
+ guint senddata:1;
+ guint reserved:22;
+ } flags;
+ glong allflags;
+ } u;
+ guint8 isdrop; /* This gdk event can be generated by a couple of
+ X events - this lets the app know whether the
+ drop really occurred or we just set the data */
+
+ GdkPoint drop_coords;
+ gchar *data_type;
+ guint32 timestamp;
+};
-<tscreen><verb>
-struct _GdkEventAny
+struct _GdkEventDragBegin
{
GdkEventType type;
GdkWindow *window;
gint8 send_event;
+ union {
+ struct {
+ guint protocol_version:4;
+ guint reserved:28;
+ } flags;
+ glong allflags;
+ } u;
};
-struct _GdkEventExpose
+struct _GdkEventDropEnter
{
GdkEventType type;
GdkWindow *window;
gint8 send_event;
- GdkRectangle area;
- gint count; /* If non-zero, how many more events follow. */
+ guint32 requestor;
+ union {
+ struct {
+ guint protocol_version:4;
+ guint sendreply:1;
+ guint extended_typelist:1;
+ guint reserved:26;
+ } flags;
+ glong allflags;
+ } u;
};
-struct _GdkEventNoExpose
+struct _GdkEventDropLeave
{
GdkEventType type;
GdkWindow *window;
gint8 send_event;
- /* XXX: does anyone need the X major_code or minor_code fields? */
+ guint32 requestor;
+ union {
+ struct {
+ guint protocol_version:4;
+ guint reserved:28;
+ } flags;
+ glong allflags;
+ } u;
};
-struct _GdkEventVisibility
+struct _GdkEventDropDataAvailable
{
GdkEventType type;
GdkWindow *window;
gint8 send_event;
- GdkVisibilityState state;
+ guint32 requestor;
+ union {
+ struct {
+ guint protocol_version:4;
+ guint isdrop:1;
+ guint reserved:25;
+ } flags;
+ glong allflags;
+ } u;
+ gchar *data_type; /* MIME type */
+ gulong data_numbytes;
+ gpointer data;
+ guint32 timestamp;
+ GdkPoint coords;
};
-struct _GdkEventMotion
+struct _GdkEventClient
{
GdkEventType type;
GdkWindow *window;
gint8 send_event;
- guint32 time;
- gdouble x;
- gdouble y;
- gdouble pressure;
- gdouble xtilt;
- gdouble ytilt;
- guint state;
- gint16 is_hint;
- GdkInputSource source;
- guint32 deviceid;
- gdouble x_root, y_root;
+ GdkAtom message_type;
+ gushort data_format;
+ union {
+ char b[20];
+ short s[10];
+ long l[5];
+ } data;
};
-struct _GdkEventButton
+struct _GdkEventOther
{
GdkEventType type;
GdkWindow *window;
gint8 send_event;
- guint32 time;
- gdouble x;
- gdouble y;
- gdouble pressure;
- gdouble xtilt;
- gdouble ytilt;
- guint state;
- guint button;
- GdkInputSource source;
- guint32 deviceid;
- gdouble x_root, y_root;
+ GdkXEvent *xevent;
+};
+</verb></tscreen>
+
+<!-- ***************************************************************** -->
+<sect> Code Examples
+<!-- ***************************************************************** -->
+<p>
+Below are the code examples that are used in the above text
+which are not included in complete form elsewhere.
+
+<!-- ----------------------------------------------------------------- -->
+<sect1>Tictactoe
+<!-- ----------------------------------------------------------------- -->
+<sect2>tictactoe.h
+<p>
+<tscreen><verb>
+/* example-start tictactoe tictactoe.h */
+
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __TICTACTOE_H__
+#define __TICTACTOE_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkvbox.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#define TICTACTOE(obj) GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
+#define TICTACTOE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
+#define IS_TICTACTOE(obj) GTK_CHECK_TYPE (obj, tictactoe_get_type ())
+
+
+typedef struct _Tictactoe Tictactoe;
+typedef struct _TictactoeClass TictactoeClass;
+
+struct _Tictactoe
+{
+ GtkVBox vbox;
+
+ GtkWidget *buttons[3][3];
+};
+
+struct _TictactoeClass
+{
+ GtkVBoxClass parent_class;
+
+ void (* tictactoe) (Tictactoe *ttt);
+};
+
+guint tictactoe_get_type (void);
+GtkWidget* tictactoe_new (void);
+void tictactoe_clear (Tictactoe *ttt);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __TICTACTOE_H__ */
+
+/* example-end */
+</verb></tscreen>
+
+<!-- ----------------------------------------------------------------- -->
+<sect2>tictactoe.c
+<p>
+<tscreen><verb>
+/* example-start tictactoe tictactoe.c */
+
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gtk/gtksignal.h"
+#include "gtk/gtktable.h"
+#include "gtk/gtktogglebutton.h"
+#include "tictactoe.h"
+
+enum {
+ TICTACTOE_SIGNAL,
+ LAST_SIGNAL
};
-struct _GdkEventKey
+static void tictactoe_class_init (TictactoeClass *klass);
+static void tictactoe_init (Tictactoe *ttt);
+static void tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt);
+
+static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
+
+guint
+tictactoe_get_type ()
+{
+ static guint ttt_type = 0;
+
+ if (!ttt_type)
+ {
+ GtkTypeInfo ttt_info =
+ {
+ "Tictactoe",
+ sizeof (Tictactoe),
+ sizeof (TictactoeClass),
+ (GtkClassInitFunc) tictactoe_class_init,
+ (GtkObjectInitFunc) tictactoe_init,
+ (GtkArgSetFunc) NULL,
+ (GtkArgGetFunc) NULL
+ };
+
+ ttt_type = gtk_type_unique (gtk_vbox_get_type (), &ttt_info);
+ }
+
+ return ttt_type;
+}
+
+static void
+tictactoe_class_init (TictactoeClass *class)
{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- guint32 time;
- guint state;
- guint keyval;
- gint length;
- gchar *string;
-};
+ GtkObjectClass *object_class;
-struct _GdkEventCrossing
-{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- GdkWindow *subwindow;
- GdkNotifyType detail;
-};
+ object_class = (GtkObjectClass*) class;
+
+ tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
+ GTK_RUN_FIRST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),
+ gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
-struct _GdkEventFocus
-{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- gint16 in;
-};
-struct _GdkEventConfigure
-{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- gint16 x, y;
- gint16 width;
- gint16 height;
-};
+ gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
-struct _GdkEventProperty
-{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- GdkAtom atom;
- guint32 time;
- guint state;
-};
+ class->tictactoe = NULL;
+}
-struct _GdkEventSelection
+static void
+tictactoe_init (Tictactoe *ttt)
{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- GdkAtom selection;
- GdkAtom target;
- GdkAtom property;
- guint32 requestor;
- guint32 time;
-};
+ GtkWidget *table;
+ gint i,j;
+
+ table = gtk_table_new (3, 3, TRUE);
+ gtk_container_add (GTK_CONTAINER(ttt), table);
+ gtk_widget_show (table);
-/* This event type will be used pretty rarely. It only is important
- for XInput aware programs that are drawing their own cursor */
+ for (i=0;i<3; i++)
+ for (j=0;j<3; j++)
+ {
+ ttt->buttons[i][j] = gtk_toggle_button_new ();
+ gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j],
+ i, i+1, j, j+1);
+ gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
+ GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
+ gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
+ gtk_widget_show (ttt->buttons[i][j]);
+ }
+}
-struct _GdkEventProximity
+GtkWidget*
+tictactoe_new ()
{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- guint32 time;
- GdkInputSource source;
- guint32 deviceid;
-};
+ return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
+}
-struct _GdkEventDragRequest
+void
+tictactoe_clear (Tictactoe *ttt)
{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- guint32 requestor;
- union {
- struct {
- guint protocol_version:4;
- guint sendreply:1;
- guint willaccept:1;
- guint delete_data:1; /* Do *not* delete if link is sent, only
- if data is sent */
- guint senddata:1;
- guint reserved:22;
- } flags;
- glong allflags;
- } u;
- guint8 isdrop; /* This gdk event can be generated by a couple of
- X events - this lets the app know whether the
- drop really occurred or we just set the data */
+ int i,j;
- GdkPoint drop_coords;
- gchar *data_type;
- guint32 timestamp;
-};
+ for (i=0;i<3;i++)
+ for (j=0;j<3;j++)
+ {
+ gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
+ FALSE);
+ gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
+ }
+}
-struct _GdkEventDragBegin
+static void
+tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- union {
- struct {
- guint protocol_version:4;
- guint reserved:28;
- } flags;
- glong allflags;
- } u;
-};
+ int i,k;
-struct _GdkEventDropEnter
-{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- guint32 requestor;
- union {
- struct {
- guint protocol_version:4;
- guint sendreply:1;
- guint extended_typelist:1;
- guint reserved:26;
- } flags;
- glong allflags;
- } u;
-};
+ static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
+ { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
+ { 0, 1, 2 }, { 0, 1, 2 } };
+ static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
+ { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
+ { 0, 1, 2 }, { 2, 1, 0 } };
-struct _GdkEventDropLeave
-{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- guint32 requestor;
- union {
- struct {
- guint protocol_version:4;
- guint reserved:28;
- } flags;
- glong allflags;
- } u;
-};
+ int success, found;
-struct _GdkEventDropDataAvailable
-{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- guint32 requestor;
- union {
- struct {
- guint protocol_version:4;
- guint isdrop:1;
- guint reserved:25;
- } flags;
- glong allflags;
- } u;
- gchar *data_type; /* MIME type */
- gulong data_numbytes;
- gpointer data;
- guint32 timestamp;
- GdkPoint coords;
-};
+ for (k=0; k<8; k++)
+ {
+ success = TRUE;
+ found = FALSE;
-struct _GdkEventClient
-{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- GdkAtom message_type;
- gushort data_format;
- union {
- char b[20];
- short s[10];
- long l[5];
- } data;
-};
+ for (i=0;i<3;i++)
+ {
+ success = success &&
+ GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
+ found = found ||
+ ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
+ }
+
+ if (success && found)
+ {
+ gtk_signal_emit (GTK_OBJECT (ttt),
+ tictactoe_signals[TICTACTOE_SIGNAL]);
+ break;
+ }
+ }
+}
+
+/* example-end */
+</verb></tscreen>
+
+<!-- ----------------------------------------------------------------- -->
+<sect2>ttt_test.c
+<p>
+<tscreen><verb>
+/* example-start tictactoe ttt_test.c */
+
+#include <gtk/gtk.h>
+#include "tictactoe.h"
+
+void
+win (GtkWidget *widget, gpointer data)
+{
+ g_print ("Yay!\n");
+ tictactoe_clear (TICTACTOE (widget));
+}
-struct _GdkEventOther
+int
+main (int argc, char *argv[])
{
- GdkEventType type;
- GdkWindow *window;
- gint8 send_event;
- GdkXEvent *xevent;
-};
-</verb></tscreen>
+ GtkWidget *window;
+ GtkWidget *ttt;
+
+ gtk_init (&argc, &argv);
-<!-- ***************************************************************** -->
-<sect> Code Examples
-<!-- ***************************************************************** -->
-<p>
-Below are the code examples that are used in the above text
-which are not included in complete form elsewhere.
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
+
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ GTK_SIGNAL_FUNC (gtk_exit), NULL);
+
+ gtk_container_set_border_width (GTK_CONTAINER (window), 10);
+
+ ttt = tictactoe_new ();
+
+ gtk_container_add (GTK_CONTAINER (window), ttt);
+ gtk_widget_show (ttt);
+
+ gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
+ GTK_SIGNAL_FUNC (win), NULL);
+
+ gtk_widget_show (window);
+
+ gtk_main ();
+
+ return 0;
+}
+
+/* example-end */
+</verb></tscreen>
<!-- ----------------------------------------------------------------- -->
-<sect1>Tictactoe
+<sect1> GtkDial
+
<!-- ----------------------------------------------------------------- -->
-<sect2>tictactoe.h
+<sect2> gtkdial.h
<p>
<tscreen><verb>
-/* example-start tictactoe tictactoe.h */
+/* example-start gtkdial gtkdial.h */
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
-#ifndef __TICTACTOE_H__
-#define __TICTACTOE_H__
+#ifndef __GTK_DIAL_H__
+#define __GTK_DIAL_H__
#include <gdk/gdk.h>
-#include <gtk/gtkvbox.h>
+#include <gtk/gtkadjustment.h>
+#include <gtk/gtkwidget.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
-#define TICTACTOE(obj) GTK_CHECK_CAST (obj, tictactoe_get_type (), Tictactoe)
-#define TICTACTOE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, tictactoe_get_type (), TictactoeClass)
-#define IS_TICTACTOE(obj) GTK_CHECK_TYPE (obj, tictactoe_get_type ())
+#define GTK_DIAL(obj) GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
+#define GTK_DIAL_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
+#define GTK_IS_DIAL(obj) GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
-typedef struct _Tictactoe Tictactoe;
-typedef struct _TictactoeClass TictactoeClass;
-struct _Tictactoe
+typedef struct _GtkDial GtkDial;
+typedef struct _GtkDialClass GtkDialClass;
+
+struct _GtkDial
{
- GtkVBox vbox;
-
- GtkWidget *buttons[3][3];
+ GtkWidget widget;
+
+ /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
+ guint policy : 2;
+
+ /* Button currently pressed or 0 if none */
+ guint8 button;
+
+ /* Dimensions of dial components */
+ gint radius;
+ gint pointer_width;
+
+ /* ID of update timer, or 0 if none */
+ guint32 timer;
+
+ /* Current angle */
+ gfloat angle;
+
+ /* Old values from adjustment stored so we know when something changes */
+ gfloat old_value;
+ gfloat old_lower;
+ gfloat old_upper;
+
+ /* The adjustment object that stores the data for this dial */
+ GtkAdjustment *adjustment;
};
-struct _TictactoeClass
+struct _GtkDialClass
{
- GtkVBoxClass parent_class;
-
- void (* tictactoe) (Tictactoe *ttt);
+ GtkWidgetClass parent_class;
};
-guint tictactoe_get_type (void);
-GtkWidget* tictactoe_new (void);
-void tictactoe_clear (Tictactoe *ttt);
+GtkWidget* gtk_dial_new (GtkAdjustment *adjustment);
+guint gtk_dial_get_type (void);
+GtkAdjustment* gtk_dial_get_adjustment (GtkDial *dial);
+void gtk_dial_set_update_policy (GtkDial *dial,
+ GtkUpdateType policy);
+
+void gtk_dial_set_adjustment (GtkDial *dial,
+ GtkAdjustment *adjustment);
#ifdef __cplusplus
}
#endif /* __cplusplus */
-#endif /* __TICTACTOE_H__ */
+#endif /* __GTK_DIAL_H__ */
/* example-end */
</verb></tscreen>
<!-- ----------------------------------------------------------------- -->
-<sect2>tictactoe.c
+<sect2> gtkdial.c
<p>
<tscreen><verb>
-/* example-start tictactoe tictactoe.c */
+/* example-start gtkdial gtkdial.c */
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
-#include "gtk/gtksignal.h"
-#include "gtk/gtktable.h"
-#include "gtk/gtktogglebutton.h"
-#include "tictactoe.h"
+#include <math.h>
+#include <stdio.h>
+#include <gtk/gtkmain.h>
+#include <gtk/gtksignal.h>
-enum {
- TICTACTOE_SIGNAL,
- LAST_SIGNAL
-};
+#include "gtkdial.h"
-static void tictactoe_class_init (TictactoeClass *klass);
-static void tictactoe_init (Tictactoe *ttt);
-static void tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt);
+#define SCROLL_DELAY_LENGTH 300
+#define DIAL_DEFAULT_SIZE 100
-static gint tictactoe_signals[LAST_SIGNAL] = { 0 };
+/* Forward declarations */
+
+static void gtk_dial_class_init (GtkDialClass *klass);
+static void gtk_dial_init (GtkDial *dial);
+static void gtk_dial_destroy (GtkObject *object);
+static void gtk_dial_realize (GtkWidget *widget);
+static void gtk_dial_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void gtk_dial_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static gint gtk_dial_expose (GtkWidget *widget,
+ GdkEventExpose *event);
+static gint gtk_dial_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_dial_button_release (GtkWidget *widget,
+ GdkEventButton *event);
+static gint gtk_dial_motion_notify (GtkWidget *widget,
+ GdkEventMotion *event);
+static gint gtk_dial_timer (GtkDial *dial);
+
+static void gtk_dial_update_mouse (GtkDial *dial, gint x, gint y);
+static void gtk_dial_update (GtkDial *dial);
+static void gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
+ gpointer data);
+static void gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
+ gpointer data);
+
+/* Local data */
+
+static GtkWidgetClass *parent_class = NULL;
guint
-tictactoe_get_type ()
+gtk_dial_get_type ()
{
- static guint ttt_type = 0;
+ static guint dial_type = 0;
- if (!ttt_type)
+ if (!dial_type)
{
- GtkTypeInfo ttt_info =
+ GtkTypeInfo dial_info =
{
- "Tictactoe",
- sizeof (Tictactoe),
- sizeof (TictactoeClass),
- (GtkClassInitFunc) tictactoe_class_init,
- (GtkObjectInitFunc) tictactoe_init,
- (GtkArgSetFunc) NULL,
- (GtkArgGetFunc) NULL
+ "GtkDial",
+ sizeof (GtkDial),
+ sizeof (GtkDialClass),
+ (GtkClassInitFunc) gtk_dial_class_init,
+ (GtkObjectInitFunc) gtk_dial_init,
+ (GtkArgSetFunc) NULL,
+ (GtkArgGetFunc) NULL,
};
- ttt_type = gtk_type_unique (gtk_vbox_get_type (), &ttt_info);
+ dial_type = gtk_type_unique (gtk_widget_get_type (), &dial_info);
}
- return ttt_type;
+ return dial_type;
}
static void
-tictactoe_class_init (TictactoeClass *class)
+gtk_dial_class_init (GtkDialClass *class)
{
GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+
+ parent_class = gtk_type_class (gtk_widget_get_type ());
+
+ object_class->destroy = gtk_dial_destroy;
+
+ widget_class->realize = gtk_dial_realize;
+ widget_class->expose_event = gtk_dial_expose;
+ widget_class->size_request = gtk_dial_size_request;
+ widget_class->size_allocate = gtk_dial_size_allocate;
+ widget_class->button_press_event = gtk_dial_button_press;
+ widget_class->button_release_event = gtk_dial_button_release;
+ widget_class->motion_notify_event = gtk_dial_motion_notify;
+}
+
+static void
+gtk_dial_init (GtkDial *dial)
+{
+ dial->button = 0;
+ dial->policy = GTK_UPDATE_CONTINUOUS;
+ dial->timer = 0;
+ dial->radius = 0;
+ dial->pointer_width = 0;
+ dial->angle = 0.0;
+ dial->old_value = 0.0;
+ dial->old_lower = 0.0;
+ dial->old_upper = 0.0;
+ dial->adjustment = NULL;
+}
+
+GtkWidget*
+gtk_dial_new (GtkAdjustment *adjustment)
+{
+ GtkDial *dial;
+
+ dial = gtk_type_new (gtk_dial_get_type ());
+
+ if (!adjustment)
+ adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+
+ gtk_dial_set_adjustment (dial, adjustment);
+
+ return GTK_WIDGET (dial);
+}
+
+static void
+gtk_dial_destroy (GtkObject *object)
+{
+ GtkDial *dial;
- object_class = (GtkObjectClass*) class;
-
- tictactoe_signals[TICTACTOE_SIGNAL] = gtk_signal_new ("tictactoe",
- GTK_RUN_FIRST,
- object_class->type,
- GTK_SIGNAL_OFFSET (TictactoeClass, tictactoe),
- gtk_signal_default_marshaller, GTK_TYPE_NONE, 0);
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_DIAL (object));
+ dial = GTK_DIAL (object);
- gtk_object_class_add_signals (object_class, tictactoe_signals, LAST_SIGNAL);
+ if (dial->adjustment)
+ gtk_object_unref (GTK_OBJECT (dial->adjustment));
- class->tictactoe = NULL;
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
}
-static void
-tictactoe_init (Tictactoe *ttt)
+GtkAdjustment*
+gtk_dial_get_adjustment (GtkDial *dial)
{
- GtkWidget *table;
- gint i,j;
-
- table = gtk_table_new (3, 3, TRUE);
- gtk_container_add (GTK_CONTAINER(ttt), table);
- gtk_widget_show (table);
+ g_return_val_if_fail (dial != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
- for (i=0;i<3; i++)
- for (j=0;j<3; j++)
- {
- ttt->buttons[i][j] = gtk_toggle_button_new ();
- gtk_table_attach_defaults (GTK_TABLE(table), ttt->buttons[i][j],
- i, i+1, j, j+1);
- gtk_signal_connect (GTK_OBJECT (ttt->buttons[i][j]), "toggled",
- GTK_SIGNAL_FUNC (tictactoe_toggle), ttt);
- gtk_widget_set_usize (ttt->buttons[i][j], 20, 20);
- gtk_widget_show (ttt->buttons[i][j]);
- }
+ return dial->adjustment;
}
-GtkWidget*
-tictactoe_new ()
+void
+gtk_dial_set_update_policy (GtkDial *dial,
+ GtkUpdateType policy)
{
- return GTK_WIDGET ( gtk_type_new (tictactoe_get_type ()));
+ g_return_if_fail (dial != NULL);
+ g_return_if_fail (GTK_IS_DIAL (dial));
+
+ dial->policy = policy;
}
-void
-tictactoe_clear (Tictactoe *ttt)
+void
+gtk_dial_set_adjustment (GtkDial *dial,
+ GtkAdjustment *adjustment)
{
- int i,j;
+ g_return_if_fail (dial != NULL);
+ g_return_if_fail (GTK_IS_DIAL (dial));
- for (i=0;i<3;i++)
- for (j=0;j<3;j++)
- {
- gtk_signal_handler_block_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ttt->buttons[i][j]),
- FALSE);
- gtk_signal_handler_unblock_by_data (GTK_OBJECT(ttt->buttons[i][j]), ttt);
- }
+ if (dial->adjustment)
+ {
+ gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
+ gtk_object_unref (GTK_OBJECT (dial->adjustment));
+ }
+
+ dial->adjustment = adjustment;
+ gtk_object_ref (GTK_OBJECT (dial->adjustment));
+
+ gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
+ (GtkSignalFunc) gtk_dial_adjustment_changed,
+ (gpointer) dial);
+ gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+ (GtkSignalFunc) gtk_dial_adjustment_value_changed,
+ (gpointer) dial);
+
+ dial->old_value = adjustment->value;
+ dial->old_lower = adjustment->lower;
+ dial->old_upper = adjustment->upper;
+
+ gtk_dial_update (dial);
}
static void
-tictactoe_toggle (GtkWidget *widget, Tictactoe *ttt)
+gtk_dial_realize (GtkWidget *widget)
{
- int i,k;
+ GtkDial *dial;
+ GdkWindowAttr attributes;
+ gint attributes_mask;
- static int rwins[8][3] = { { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
- { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
- { 0, 1, 2 }, { 0, 1, 2 } };
- static int cwins[8][3] = { { 0, 1, 2 }, { 0, 1, 2 }, { 0, 1, 2 },
- { 0, 0, 0 }, { 1, 1, 1 }, { 2, 2, 2 },
- { 0, 1, 2 }, { 2, 1, 0 } };
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_DIAL (widget));
- int success, found;
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+ dial = GTK_DIAL (widget);
- for (k=0; k<8; k++)
- {
- success = TRUE;
- found = FALSE;
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.event_mask = gtk_widget_get_events (widget) |
+ GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
+ GDK_POINTER_MOTION_HINT_MASK;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
- for (i=0;i<3;i++)
- {
- success = success &&
- GTK_TOGGLE_BUTTON(ttt->buttons[rwins[k][i]][cwins[k][i]])->active;
- found = found ||
- ttt->buttons[rwins[k][i]][cwins[k][i]] == widget;
- }
-
- if (success && found)
- {
- gtk_signal_emit (GTK_OBJECT (ttt),
- tictactoe_signals[TICTACTOE_SIGNAL]);
- break;
- }
- }
-}
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+ widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
-/* example-end */
-</verb></tscreen>
+ widget->style = gtk_style_attach (widget->style, widget->window);
-<!-- ----------------------------------------------------------------- -->
-<sect2>ttt_test.c
-<p>
-<tscreen><verb>
-/* example-start tictactoe ttt_test.c */
+ gdk_window_set_user_data (widget->window, widget);
-#include <gtk/gtk.h>
-#include "tictactoe.h"
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
+}
-void
-win (GtkWidget *widget, gpointer data)
+static void
+gtk_dial_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
{
- g_print ("Yay!\n");
- tictactoe_clear (TICTACTOE (widget));
+ requisition->width = DIAL_DEFAULT_SIZE;
+ requisition->height = DIAL_DEFAULT_SIZE;
}
-int
-main (int argc, char *argv[])
+static void
+gtk_dial_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
{
- GtkWidget *window;
- GtkWidget *ttt;
-
- gtk_init (&argc, &argv);
+ GtkDial *dial;
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-
- gtk_window_set_title (GTK_WINDOW (window), "Aspect Frame");
-
- gtk_signal_connect (GTK_OBJECT (window), "destroy",
- GTK_SIGNAL_FUNC (gtk_exit), NULL);
-
- gtk_container_set_border_width (GTK_CONTAINER (window), 10);
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_DIAL (widget));
+ g_return_if_fail (allocation != NULL);
- ttt = tictactoe_new ();
-
- gtk_container_add (GTK_CONTAINER (window), ttt);
- gtk_widget_show (ttt);
+ widget->allocation = *allocation;
+ dial = GTK_DIAL (widget);
- gtk_signal_connect (GTK_OBJECT (ttt), "tictactoe",
- GTK_SIGNAL_FUNC (win), NULL);
+ if (GTK_WIDGET_REALIZED (widget))
+ {
- gtk_widget_show (window);
-
- gtk_main ();
-
- return 0;
+ gdk_window_move_resize (widget->window,
+ allocation->x, allocation->y,
+ allocation->width, allocation->height);
+
+ }
+ dial->radius = MIN(allocation->width,allocation->height) * 0.45;
+ dial->pointer_width = dial->radius / 5;
}
-/* example-end */
-</verb></tscreen>
+static gint
+gtk_dial_expose (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ GtkDial *dial;
+ GdkPoint points[3];
+ gdouble s,c;
+ gdouble theta;
+ gint xc, yc;
+ gint tick_length;
+ gint i;
-<!-- ----------------------------------------------------------------- -->
-<sect1> GtkDial
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
-<!-- ----------------------------------------------------------------- -->
-<sect2> gtkdial.h
-<p>
-<tscreen><verb>
-/* example-start gtkdial gtkdial.h */
+ if (event->count > 0)
+ return FALSE;
+
+ dial = GTK_DIAL (widget);
-/* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-#ifndef __GTK_DIAL_H__
-#define __GTK_DIAL_H__
+ gdk_window_clear_area (widget->window,
+ 0, 0,
+ widget->allocation.width,
+ widget->allocation.height);
+
+ xc = widget->allocation.width/2;
+ yc = widget->allocation.height/2;
+ /* Draw ticks */
-#include <gdk/gdk.h>
-#include <gtk/gtkadjustment.h>
-#include <gtk/gtkwidget.h>
+ for (i=0; i<25; i++)
+ {
+ theta = (i*M_PI/18. - M_PI/6.);
+ s = sin(theta);
+ c = cos(theta);
+ tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
+
+ gdk_draw_line (widget->window,
+ widget->style->fg_gc[widget->state],
+ xc + c*(dial->radius - tick_length),
+ yc - s*(dial->radius - tick_length),
+ xc + c*dial->radius,
+ yc - s*dial->radius);
+ }
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
+ /* Draw pointer */
+ s = sin(dial->angle);
+ c = cos(dial->angle);
-#define GTK_DIAL(obj) GTK_CHECK_CAST (obj, gtk_dial_get_type (), GtkDial)
-#define GTK_DIAL_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_dial_get_type (), GtkDialClass)
-#define GTK_IS_DIAL(obj) GTK_CHECK_TYPE (obj, gtk_dial_get_type ())
+ points[0].x = xc + s*dial->pointer_width/2;
+ points[0].y = yc + c*dial->pointer_width/2;
+ points[1].x = xc + c*dial->radius;
+ points[1].y = yc - s*dial->radius;
+ points[2].x = xc - s*dial->pointer_width/2;
+ points[2].y = yc - c*dial->pointer_width/2;
-typedef struct _GtkDial GtkDial;
-typedef struct _GtkDialClass GtkDialClass;
+ gtk_draw_polygon (widget->style,
+ widget->window,
+ GTK_STATE_NORMAL,
+ GTK_SHADOW_OUT,
+ points, 3,
+ TRUE);
+
+ return FALSE;
+}
-struct _GtkDial
+static gint
+gtk_dial_button_press (GtkWidget *widget,
+ GdkEventButton *event)
{
- GtkWidget widget;
-
- /* update policy (GTK_UPDATE_[CONTINUOUS/DELAYED/DISCONTINUOUS]) */
- guint policy : 2;
+ GtkDial *dial;
+ gint dx, dy;
+ double s, c;
+ double d_parallel;
+ double d_perpendicular;
- /* Button currently pressed or 0 if none */
- guint8 button;
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
- /* Dimensions of dial components */
- gint radius;
- gint pointer_width;
+ dial = GTK_DIAL (widget);
- /* ID of update timer, or 0 if none */
- guint32 timer;
+ /* Determine if button press was within pointer region - we
+ do this by computing the parallel and perpendicular distance of
+ the point where the mouse was pressed from the line passing through
+ the pointer */
+
+ dx = event->x - widget->allocation.width / 2;
+ dy = widget->allocation.height / 2 - event->y;
+
+ s = sin(dial->angle);
+ c = cos(dial->angle);
+
+ d_parallel = s*dy + c*dx;
+ d_perpendicular = fabs(s*dx - c*dy);
+
+ if (!dial->button &&
+ (d_perpendicular < dial->pointer_width/2) &&
+ (d_parallel > - dial->pointer_width))
+ {
+ gtk_grab_add (widget);
- /* Current angle */
- gfloat angle;
+ dial->button = event->button;
- /* Old values from adjustment stored so we know when something changes */
- gfloat old_value;
- gfloat old_lower;
- gfloat old_upper;
+ gtk_dial_update_mouse (dial, event->x, event->y);
+ }
- /* The adjustment object that stores the data for this dial */
- GtkAdjustment *adjustment;
-};
+ return FALSE;
+}
-struct _GtkDialClass
+static gint
+gtk_dial_button_release (GtkWidget *widget,
+ GdkEventButton *event)
{
- GtkWidgetClass parent_class;
-};
+ GtkDial *dial;
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
-GtkWidget* gtk_dial_new (GtkAdjustment *adjustment);
-guint gtk_dial_get_type (void);
-GtkAdjustment* gtk_dial_get_adjustment (GtkDial *dial);
-void gtk_dial_set_update_policy (GtkDial *dial,
- GtkUpdateType policy);
+ dial = GTK_DIAL (widget);
-void gtk_dial_set_adjustment (GtkDial *dial,
- GtkAdjustment *adjustment);
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+ if (dial->button == event->button)
+ {
+ gtk_grab_remove (widget);
+ dial->button = 0;
-#endif /* __GTK_DIAL_H__ */
-/* example-end */
-</verb></tscreen>
+ if (dial->policy == GTK_UPDATE_DELAYED)
+ gtk_timeout_remove (dial->timer);
+
+ if ((dial->policy != GTK_UPDATE_CONTINUOUS) &&
+ (dial->old_value != dial->adjustment->value))
+ gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
+ }
-<!-- ----------------------------------------------------------------- -->
-<sect2> gtkdial.c
-<p>
-<tscreen><verb>
-/* example-start gtkdial gtkdial.c */
+ return FALSE;
+}
-/* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-#include <math.h>
-#include <stdio.h>
-#include <gtk/gtkmain.h>
-#include <gtk/gtksignal.h>
+static gint
+gtk_dial_motion_notify (GtkWidget *widget,
+ GdkEventMotion *event)
+{
+ GtkDial *dial;
+ GdkModifierType mods;
+ gint x, y, mask;
-#include "gtkdial.h"
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
-#define SCROLL_DELAY_LENGTH 300
-#define DIAL_DEFAULT_SIZE 100
+ dial = GTK_DIAL (widget);
-/* Forward declarations */
+ if (dial->button != 0)
+ {
+ x = event->x;
+ y = event->y;
-static void gtk_dial_class_init (GtkDialClass *klass);
-static void gtk_dial_init (GtkDial *dial);
-static void gtk_dial_destroy (GtkObject *object);
-static void gtk_dial_realize (GtkWidget *widget);
-static void gtk_dial_size_request (GtkWidget *widget,
- GtkRequisition *requisition);
-static void gtk_dial_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation);
-static gint gtk_dial_expose (GtkWidget *widget,
- GdkEventExpose *event);
-static gint gtk_dial_button_press (GtkWidget *widget,
- GdkEventButton *event);
-static gint gtk_dial_button_release (GtkWidget *widget,
- GdkEventButton *event);
-static gint gtk_dial_motion_notify (GtkWidget *widget,
- GdkEventMotion *event);
-static gint gtk_dial_timer (GtkDial *dial);
+ if (event->is_hint || (event->window != widget->window))
+ gdk_window_get_pointer (widget->window, &x, &y, &mods);
-static void gtk_dial_update_mouse (GtkDial *dial, gint x, gint y);
-static void gtk_dial_update (GtkDial *dial);
-static void gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
- gpointer data);
-static void gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
- gpointer data);
+ switch (dial->button)
+ {
+ case 1:
+ mask = GDK_BUTTON1_MASK;
+ break;
+ case 2:
+ mask = GDK_BUTTON2_MASK;
+ break;
+ case 3:
+ mask = GDK_BUTTON3_MASK;
+ break;
+ default:
+ mask = 0;
+ break;
+ }
-/* Local data */
+ if (mods & mask)
+ gtk_dial_update_mouse (dial, x,y);
+ }
-static GtkWidgetClass *parent_class = NULL;
+ return FALSE;
+}
-guint
-gtk_dial_get_type ()
+static gint
+gtk_dial_timer (GtkDial *dial)
{
- static guint dial_type = 0;
-
- if (!dial_type)
- {
- GtkTypeInfo dial_info =
- {
- "GtkDial",
- sizeof (GtkDial),
- sizeof (GtkDialClass),
- (GtkClassInitFunc) gtk_dial_class_init,
- (GtkObjectInitFunc) gtk_dial_init,
- (GtkArgSetFunc) NULL,
- (GtkArgGetFunc) NULL,
- };
+ g_return_val_if_fail (dial != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
- dial_type = gtk_type_unique (gtk_widget_get_type (), &dial_info);
- }
+ if (dial->policy == GTK_UPDATE_DELAYED)
+ gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
- return dial_type;
+ return FALSE;
}
static void
-gtk_dial_class_init (GtkDialClass *class)
+gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
{
- GtkObjectClass *object_class;
- GtkWidgetClass *widget_class;
+ gint xc, yc;
+ gfloat old_value;
- object_class = (GtkObjectClass*) class;
- widget_class = (GtkWidgetClass*) class;
+ g_return_if_fail (dial != NULL);
+ g_return_if_fail (GTK_IS_DIAL (dial));
- parent_class = gtk_type_class (gtk_widget_get_type ());
+ xc = GTK_WIDGET(dial)->allocation.width / 2;
+ yc = GTK_WIDGET(dial)->allocation.height / 2;
- object_class->destroy = gtk_dial_destroy;
+ old_value = dial->adjustment->value;
+ dial->angle = atan2(yc-y, x-xc);
- widget_class->realize = gtk_dial_realize;
- widget_class->expose_event = gtk_dial_expose;
- widget_class->size_request = gtk_dial_size_request;
- widget_class->size_allocate = gtk_dial_size_allocate;
- widget_class->button_press_event = gtk_dial_button_press;
- widget_class->button_release_event = gtk_dial_button_release;
- widget_class->motion_notify_event = gtk_dial_motion_notify;
-}
+ if (dial->angle < -M_PI/2.)
+ dial->angle += 2*M_PI;
-static void
-gtk_dial_init (GtkDial *dial)
-{
- dial->button = 0;
- dial->policy = GTK_UPDATE_CONTINUOUS;
- dial->timer = 0;
- dial->radius = 0;
- dial->pointer_width = 0;
- dial->angle = 0.0;
- dial->old_value = 0.0;
- dial->old_lower = 0.0;
- dial->old_upper = 0.0;
- dial->adjustment = NULL;
-}
+ if (dial->angle < -M_PI/6)
+ dial->angle = -M_PI/6;
-GtkWidget*
-gtk_dial_new (GtkAdjustment *adjustment)
-{
- GtkDial *dial;
+ if (dial->angle > 7.*M_PI/6.)
+ dial->angle = 7.*M_PI/6.;
- dial = gtk_type_new (gtk_dial_get_type ());
+ dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
+ (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
- if (!adjustment)
- adjustment = (GtkAdjustment*) gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+ if (dial->adjustment->value != old_value)
+ {
+ if (dial->policy == GTK_UPDATE_CONTINUOUS)
+ {
+ gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
+ }
+ else
+ {
+ gtk_widget_draw (GTK_WIDGET(dial), NULL);
- gtk_dial_set_adjustment (dial, adjustment);
+ if (dial->policy == GTK_UPDATE_DELAYED)
+ {
+ if (dial->timer)
+ gtk_timeout_remove (dial->timer);
- return GTK_WIDGET (dial);
+ dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
+ (GtkFunction) gtk_dial_timer,
+ (gpointer) dial);
+ }
+ }
+ }
}
static void
-gtk_dial_destroy (GtkObject *object)
+gtk_dial_update (GtkDial *dial)
{
- GtkDial *dial;
-
- g_return_if_fail (object != NULL);
- g_return_if_fail (GTK_IS_DIAL (object));
+ gfloat new_value;
+
+ g_return_if_fail (dial != NULL);
+ g_return_if_fail (GTK_IS_DIAL (dial));
- dial = GTK_DIAL (object);
+ new_value = dial->adjustment->value;
+
+ if (new_value < dial->adjustment->lower)
+ new_value = dial->adjustment->lower;
- if (dial->adjustment)
- gtk_object_unref (GTK_OBJECT (dial->adjustment));
+ if (new_value > dial->adjustment->upper)
+ new_value = dial->adjustment->upper;
- if (GTK_OBJECT_CLASS (parent_class)->destroy)
- (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
-}
+ if (new_value != dial->adjustment->value)
+ {
+ dial->adjustment->value = new_value;
+ gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
+ }
-GtkAdjustment*
-gtk_dial_get_adjustment (GtkDial *dial)
-{
- g_return_val_if_fail (dial != NULL, NULL);
- g_return_val_if_fail (GTK_IS_DIAL (dial), NULL);
+ dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
+ (dial->adjustment->upper - dial->adjustment->lower);
- return dial->adjustment;
+ gtk_widget_draw (GTK_WIDGET(dial), NULL);
}
-void
-gtk_dial_set_update_policy (GtkDial *dial,
- GtkUpdateType policy)
+static void
+gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
+ gpointer data)
{
- g_return_if_fail (dial != NULL);
- g_return_if_fail (GTK_IS_DIAL (dial));
+ GtkDial *dial;
- dial->policy = policy;
-}
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (data != NULL);
-void
-gtk_dial_set_adjustment (GtkDial *dial,
- GtkAdjustment *adjustment)
-{
- g_return_if_fail (dial != NULL);
- g_return_if_fail (GTK_IS_DIAL (dial));
+ dial = GTK_DIAL (data);
- if (dial->adjustment)
+ if ((dial->old_value != adjustment->value) ||
+ (dial->old_lower != adjustment->lower) ||
+ (dial->old_upper != adjustment->upper))
{
- gtk_signal_disconnect_by_data (GTK_OBJECT (dial->adjustment), (gpointer) dial);
- gtk_object_unref (GTK_OBJECT (dial->adjustment));
- }
-
- dial->adjustment = adjustment;
- gtk_object_ref (GTK_OBJECT (dial->adjustment));
-
- gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
- (GtkSignalFunc) gtk_dial_adjustment_changed,
- (gpointer) dial);
- gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
- (GtkSignalFunc) gtk_dial_adjustment_value_changed,
- (gpointer) dial);
-
- dial->old_value = adjustment->value;
- dial->old_lower = adjustment->lower;
- dial->old_upper = adjustment->upper;
+ gtk_dial_update (dial);
- gtk_dial_update (dial);
+ dial->old_value = adjustment->value;
+ dial->old_lower = adjustment->lower;
+ dial->old_upper = adjustment->upper;
+ }
}
static void
-gtk_dial_realize (GtkWidget *widget)
+gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
+ gpointer data)
{
GtkDial *dial;
- GdkWindowAttr attributes;
- gint attributes_mask;
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_DIAL (widget));
+ g_return_if_fail (adjustment != NULL);
+ g_return_if_fail (data != NULL);
- GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
- dial = GTK_DIAL (widget);
+ dial = GTK_DIAL (data);
- attributes.x = widget->allocation.x;
- attributes.y = widget->allocation.y;
- attributes.width = widget->allocation.width;
- attributes.height = widget->allocation.height;
- attributes.wclass = GDK_INPUT_OUTPUT;
- attributes.window_type = GDK_WINDOW_CHILD;
- attributes.event_mask = gtk_widget_get_events (widget) |
- GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
- GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
- GDK_POINTER_MOTION_HINT_MASK;
- attributes.visual = gtk_widget_get_visual (widget);
- attributes.colormap = gtk_widget_get_colormap (widget);
+ if (dial->old_value != adjustment->value)
+ {
+ gtk_dial_update (dial);
- attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
- widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
+ dial->old_value = adjustment->value;
+ }
+}
+/* example-end */
+</verb></tscreen>
- widget->style = gtk_style_attach (widget->style, widget->window);
+<!-- ----------------------------------------------------------------- -->
+<sect1> Scribble
+<p>
+<tscreen><verb>
+/* example-start scribble-simple scribble-simple.c */
- gdk_window_set_user_data (widget->window, widget);
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
- gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
+#include <gtk/gtk.h>
+
+/* Backing pixmap for drawing area */
+static GdkPixmap *pixmap = NULL;
+
+/* Create a new backing pixmap of the appropriate size */
+static gint
+configure_event (GtkWidget *widget, GdkEventConfigure *event)
+{
+ if (pixmap)
+ gdk_pixmap_unref(pixmap);
+
+ pixmap = gdk_pixmap_new(widget->window,
+ widget->allocation.width,
+ widget->allocation.height,
+ -1);
+ gdk_draw_rectangle (pixmap,
+ widget->style->white_gc,
+ TRUE,
+ 0, 0,
+ widget->allocation.width,
+ widget->allocation.height);
+
+ return TRUE;
}
-static void
-gtk_dial_size_request (GtkWidget *widget,
- GtkRequisition *requisition)
+/* Redraw the screen from the backing pixmap */
+static gint
+expose_event (GtkWidget *widget, GdkEventExpose *event)
{
- requisition->width = DIAL_DEFAULT_SIZE;
- requisition->height = DIAL_DEFAULT_SIZE;
+ gdk_draw_pixmap(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ pixmap,
+ event->area.x, event->area.y,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+
+ return FALSE;
}
+/* Draw a rectangle on the screen */
static void
-gtk_dial_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
+draw_brush (GtkWidget *widget, gdouble x, gdouble y)
{
- GtkDial *dial;
+ GdkRectangle update_rect;
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_DIAL (widget));
- g_return_if_fail (allocation != NULL);
+ update_rect.x = x - 5;
+ update_rect.y = y - 5;
+ update_rect.width = 10;
+ update_rect.height = 10;
+ gdk_draw_rectangle (pixmap,
+ widget->style->black_gc,
+ TRUE,
+ update_rect.x, update_rect.y,
+ update_rect.width, update_rect.height);
+ gtk_widget_draw (widget, &update_rect);
+}
- widget->allocation = *allocation;
- dial = GTK_DIAL (widget);
+static gint
+button_press_event (GtkWidget *widget, GdkEventButton *event)
+{
+ if (event->button == 1 && pixmap != NULL)
+ draw_brush (widget, event->x, event->y);
- if (GTK_WIDGET_REALIZED (widget))
- {
+ return TRUE;
+}
- gdk_window_move_resize (widget->window,
- allocation->x, allocation->y,
- allocation->width, allocation->height);
+static gint
+motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
+{
+ int x, y;
+ GdkModifierType state;
+ if (event->is_hint)
+ gdk_window_get_pointer (event->window, &x, &y, &state);
+ else
+ {
+ x = event->x;
+ y = event->y;
+ state = event->state;
}
- dial->radius = MIN(allocation->width,allocation->height) * 0.45;
- dial->pointer_width = dial->radius / 5;
+
+ if (state & GDK_BUTTON1_MASK && pixmap != NULL)
+ draw_brush (widget, x, y);
+
+ return TRUE;
}
-static gint
-gtk_dial_expose (GtkWidget *widget,
- GdkEventExpose *event)
+void
+quit ()
{
- GtkDial *dial;
- GdkPoint points[3];
- gdouble s,c;
- gdouble theta;
- gint xc, yc;
- gint tick_length;
- gint i;
+ gtk_exit (0);
+}
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *window;
+ GtkWidget *drawing_area;
+ GtkWidget *vbox;
- if (event->count > 0)
- return FALSE;
-
- dial = GTK_DIAL (widget);
+ GtkWidget *button;
- gdk_window_clear_area (widget->window,
- 0, 0,
- widget->allocation.width,
- widget->allocation.height);
+ gtk_init (&argc, &argv);
- xc = widget->allocation.width/2;
- yc = widget->allocation.height/2;
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_widget_set_name (window, "Test Input");
- /* Draw ticks */
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), vbox);
+ gtk_widget_show (vbox);
- for (i=0; i<25; i++)
- {
- theta = (i*M_PI/18. - M_PI/6.);
- s = sin(theta);
- c = cos(theta);
+ gtk_signal_connect (GTK_OBJECT (window), "destroy",
+ GTK_SIGNAL_FUNC (quit), NULL);
- tick_length = (i%6 == 0) ? dial->pointer_width : dial->pointer_width/2;
-
- gdk_draw_line (widget->window,
- widget->style->fg_gc[widget->state],
- xc + c*(dial->radius - tick_length),
- yc - s*(dial->radius - tick_length),
- xc + c*dial->radius,
- yc - s*dial->radius);
- }
+ /* Create the drawing area */
- /* Draw pointer */
+ drawing_area = gtk_drawing_area_new ();
+ gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
+ gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
- s = sin(dial->angle);
- c = cos(dial->angle);
+ gtk_widget_show (drawing_area);
+ /* Signals used to handle backing pixmap */
- points[0].x = xc + s*dial->pointer_width/2;
- points[0].y = yc + c*dial->pointer_width/2;
- points[1].x = xc + c*dial->radius;
- points[1].y = yc - s*dial->radius;
- points[2].x = xc - s*dial->pointer_width/2;
- points[2].y = yc - c*dial->pointer_width/2;
+ gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
+ (GtkSignalFunc) expose_event, NULL);
+ gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
+ (GtkSignalFunc) configure_event, NULL);
- gtk_draw_polygon (widget->style,
- widget->window,
- GTK_STATE_NORMAL,
- GTK_SHADOW_OUT,
- points, 3,
- TRUE);
-
- return FALSE;
-}
+ /* Event signals */
-static gint
-gtk_dial_button_press (GtkWidget *widget,
- GdkEventButton *event)
-{
- GtkDial *dial;
- gint dx, dy;
- double s, c;
- double d_parallel;
- double d_perpendicular;
+ gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
+ (GtkSignalFunc) motion_notify_event, NULL);
+ gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
+ (GtkSignalFunc) button_press_event, NULL);
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
+ gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
+ | GDK_LEAVE_NOTIFY_MASK
+ | GDK_BUTTON_PRESS_MASK
+ | GDK_POINTER_MOTION_MASK
+ | GDK_POINTER_MOTION_HINT_MASK);
- dial = GTK_DIAL (widget);
+ /* .. And a quit button */
+ button = gtk_button_new_with_label ("Quit");
+ gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
- /* Determine if button press was within pointer region - we
- do this by computing the parallel and perpendicular distance of
- the point where the mouse was pressed from the line passing through
- the pointer */
-
- dx = event->x - widget->allocation.width / 2;
- dy = widget->allocation.height / 2 - event->y;
-
- s = sin(dial->angle);
- c = cos(dial->angle);
-
- d_parallel = s*dy + c*dx;
- d_perpendicular = fabs(s*dx - c*dy);
-
- if (!dial->button &&
- (d_perpendicular < dial->pointer_width/2) &&
- (d_parallel > - dial->pointer_width))
- {
- gtk_grab_add (widget);
+ gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+ GTK_SIGNAL_FUNC (gtk_widget_destroy),
+ GTK_OBJECT (window));
+ gtk_widget_show (button);
- dial->button = event->button;
+ gtk_widget_show (window);
- gtk_dial_update_mouse (dial, event->x, event->y);
- }
+ gtk_main ();
- return FALSE;
+ return 0;
}
+/* example-end */
+</verb></tscreen>
-static gint
-gtk_dial_button_release (GtkWidget *widget,
- GdkEventButton *event)
+<!-- ***************************************************************** -->
+<sect> List Widget
+<!-- ***************************************************************** -->
+<p>
+NOTE: The GtkList widget has been superseded by the GtkCList
+widget. It is detailed here just for completeness.
+
+The GtkList widget is designed to act as a vertical container for
+widgets that should be of the type GtkListItem.
+
+A GtkList widget has its own window to receive events and its own
+background color which is usually white. As it is directly derived
+from a GtkContainer it can be treated as such by using the
+GTK_CONTAINER(List) macro, see the GtkContainer widget for more on
+this. One should already be familiar with the usage of a GList and
+its related functions g_list_*() to be able to use the GtkList widget
+to it full extent.
+
+There is one field inside the structure definition of the GtkList
+widget that will be of greater interest to us, this is:
+
+<tscreen><verb>
+struct _GtkList
{
- GtkDial *dial;
+ ...
+ GList *selection;
+ guint selection_mode;
+ ...
+};
+</verb></tscreen>
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
+The selection field of a GtkList points to a linked list of all items
+that are currently selected, or NULL if the selection is empty. So to
+learn about the current selection we read the GTK_LIST()->selection
+field, but do not modify it since the internal fields are maintained
+by the gtk_list_*() functions.
- dial = GTK_DIAL (widget);
+The selection_mode of the GtkList determines the selection facilities
+of a GtkList and therefore the contents of the GTK_LIST()->selection
+field. The selection_mode may be one of the following:
- if (dial->button == event->button)
- {
- gtk_grab_remove (widget);
+<itemize>
+<item> GTK_SELECTION_SINGLE - The selection is either NULL
+ or contains a GList pointer
+ for a single selected item.
- dial->button = 0;
+<item> GTK_SELECTION_BROWSE - The selection is NULL if the list
+ contains no widgets or insensitive
+ ones only, otherwise it contains
+ a GList pointer for one GList
+ structure, and therefore exactly
+ one list item.
- if (dial->policy == GTK_UPDATE_DELAYED)
- gtk_timeout_remove (dial->timer);
-
- if ((dial->policy != GTK_UPDATE_CONTINUOUS) &&
- (dial->old_value != dial->adjustment->value))
- gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
- }
+<item> GTK_SELECTION_MULTIPLE - The selection is NULL if no list
+ items are selected or a GList pointer
+ for the first selected item. That
+ in turn points to a GList structure
+ for the second selected item and so
+ on.
- return FALSE;
-}
+<item> GTK_SELECTION_EXTENDED - The selection is always NULL.
+</itemize>
-static gint
-gtk_dial_motion_notify (GtkWidget *widget,
- GdkEventMotion *event)
-{
- GtkDial *dial;
- GdkModifierType mods;
- gint x, y, mask;
+The default is GTK_SELECTION_MULTIPLE.
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_DIAL (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
+<!-- ----------------------------------------------------------------- -->
+<sect1> Signals
+<p>
+<tscreen><verb>
+void selection_changed( GtkList *list );
+</verb></tscreen>
- dial = GTK_DIAL (widget);
+This signal will be invoked whenever the selection field of a GtkList
+has changed. This happens when a child of the GtkList got selected or
+deselected.
- if (dial->button != 0)
- {
- x = event->x;
- y = event->y;
+<tscreen><verb>
+void select_child( GtkList *list,
+ GtkWidget *child);
+</verb></tscreen>
- if (event->is_hint || (event->window != widget->window))
- gdk_window_get_pointer (widget->window, &x, &y, &mods);
+This signal is invoked when a child of the GtkList is about to get
+selected. This happens mainly on calls to gtk_list_select_item(),
+gtk_list_select_child(), button presses and sometimes indirectly
+triggered on some else occasions where children get added to or
+removed from the GtkList.
- switch (dial->button)
- {
- case 1:
- mask = GDK_BUTTON1_MASK;
- break;
- case 2:
- mask = GDK_BUTTON2_MASK;
- break;
- case 3:
- mask = GDK_BUTTON3_MASK;
- break;
- default:
- mask = 0;
- break;
- }
+<tscreen><verb>
+void unselect_child( GtkList *list,
+ GtkWidget *child );
+</verb></tscreen>
- if (mods & mask)
- gtk_dial_update_mouse (dial, x,y);
- }
+This signal is invoked when a child of the GtkList is about to get
+deselected. This happens mainly on calls to gtk_list_unselect_item(),
+gtk_list_unselect_child(), button presses and sometimes indirectly
+triggered on some else occasions where children get added to or
+removed from the GtkList.
- return FALSE;
-}
+<!-- ----------------------------------------------------------------- -->
+<sect1> Functions
+<p>
+<tscreen><verb>
+guint gtk_list_get_type( void );
+</verb></tscreen>
-static gint
-gtk_dial_timer (GtkDial *dial)
-{
- g_return_val_if_fail (dial != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_DIAL (dial), FALSE);
+Returns the `GtkList' type identifier.
- if (dial->policy == GTK_UPDATE_DELAYED)
- gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
+<tscreen><verb>
+GtkWidget *gtk_list_new( void );
+</verb></tscreen>
- return FALSE;
-}
+Create a new GtkList object. The new widget is returned as a pointer
+to a GtkWidget object. NULL is returned on failure.
-static void
-gtk_dial_update_mouse (GtkDial *dial, gint x, gint y)
-{
- gint xc, yc;
- gfloat old_value;
+<tscreen><verb>
+void gtk_list_insert_items( GtkList *list,
+ GList *items,
+ gint position );
+</verb></tscreen>
- g_return_if_fail (dial != NULL);
- g_return_if_fail (GTK_IS_DIAL (dial));
+Insert list items into the list, starting at <tt/position/.
+<tt/items/ is a doubly linked list where each nodes data pointer is
+expected to point to a newly created GtkListItem. The GList nodes of
+<tt/items/ are taken over by the list.
- xc = GTK_WIDGET(dial)->allocation.width / 2;
- yc = GTK_WIDGET(dial)->allocation.height / 2;
+<tscreen><verb>
+void gtk_list_append_items( GtkList *list,
+ GList *items);
+</verb></tscreen>
- old_value = dial->adjustment->value;
- dial->angle = atan2(yc-y, x-xc);
+Insert list items just like gtk_list_insert_items() at the end of the
+list. The GList nodes of <tt/items/ are taken over by the list.
- if (dial->angle < -M_PI/2.)
- dial->angle += 2*M_PI;
+<tscreen><verb>
+void gtk_list_prepend_items( GtkList *list,
+ GList *items);
+</verb></tscreen>
- if (dial->angle < -M_PI/6)
- dial->angle = -M_PI/6;
+Insert list items just like gtk_list_insert_items() at the very
+beginning of the list. The GList nodes of <tt/items/ are taken over by
+the list.
- if (dial->angle > 7.*M_PI/6.)
- dial->angle = 7.*M_PI/6.;
+<tscreen><verb>
+void gtk_list_remove_items( GtkList *list,
+ GList *items);
+</verb></tscreen>
- dial->adjustment->value = dial->adjustment->lower + (7.*M_PI/6 - dial->angle) *
- (dial->adjustment->upper - dial->adjustment->lower) / (4.*M_PI/3.);
+Remove list items from the list. <tt/items/ is a doubly linked list
+where each nodes data pointer is expected to point to a direct child
+of list. It is the callers responsibility to make a call to
+g_list_free(items) afterwards. Also the caller has to destroy the list
+items himself.
- if (dial->adjustment->value != old_value)
- {
- if (dial->policy == GTK_UPDATE_CONTINUOUS)
- {
- gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
- }
- else
- {
- gtk_widget_draw (GTK_WIDGET(dial), NULL);
+<tscreen><verb>
+void gtk_list_clear_items( GtkList *list,
+ gint start,
+ gint end );
+</verb></tscreen>
- if (dial->policy == GTK_UPDATE_DELAYED)
- {
- if (dial->timer)
- gtk_timeout_remove (dial->timer);
+Remove and destroy list items from the list. A widget is affected if
+its current position within the list is in the range specified by
+<tt/start/ and <tt/end/.
- dial->timer = gtk_timeout_add (SCROLL_DELAY_LENGTH,
- (GtkFunction) gtk_dial_timer,
- (gpointer) dial);
- }
- }
- }
-}
+<tscreen><verb>
+void gtk_list_select_item( GtkList *list,
+ gint item );
+</verb></tscreen>
-static void
-gtk_dial_update (GtkDial *dial)
-{
- gfloat new_value;
-
- g_return_if_fail (dial != NULL);
- g_return_if_fail (GTK_IS_DIAL (dial));
+Invoke the select_child signal for a list item specified through its
+current position within the list.
- new_value = dial->adjustment->value;
-
- if (new_value < dial->adjustment->lower)
- new_value = dial->adjustment->lower;
+<tscreen><verb>
+void gtk_list_unselect_item( GtkList *list,
+ gint item);
+</verb></tscreen>
- if (new_value > dial->adjustment->upper)
- new_value = dial->adjustment->upper;
+Invoke the unselect_child signal for a list item specified through its
+current position within the list.
- if (new_value != dial->adjustment->value)
- {
- dial->adjustment->value = new_value;
- gtk_signal_emit_by_name (GTK_OBJECT (dial->adjustment), "value_changed");
- }
+<tscreen><verb>
+void gtk_list_select_child( GtkList *list,
+ GtkWidget *child);
+</verb></tscreen>
- dial->angle = 7.*M_PI/6. - (new_value - dial->adjustment->lower) * 4.*M_PI/3. /
- (dial->adjustment->upper - dial->adjustment->lower);
+Invoke the select_child signal for the specified child.
- gtk_widget_draw (GTK_WIDGET(dial), NULL);
-}
+<tscreen><verb>
+void gtk_list_unselect_child( GtkList *list,
+ GtkWidget *child);
+</verb></tscreen>
-static void
-gtk_dial_adjustment_changed (GtkAdjustment *adjustment,
- gpointer data)
-{
- GtkDial *dial;
+Invoke the unselect_child signal for the specified child.
- g_return_if_fail (adjustment != NULL);
- g_return_if_fail (data != NULL);
+<tscreen><verb>
+gint gtk_list_child_position( GtkList *list,
+ GtkWidget *child);
+</verb></tscreen>
- dial = GTK_DIAL (data);
+Return the position of <tt/child/ within the list. "-1" is returned on
+failure.
- if ((dial->old_value != adjustment->value) ||
- (dial->old_lower != adjustment->lower) ||
- (dial->old_upper != adjustment->upper))
- {
- gtk_dial_update (dial);
+<tscreen><verb>
+void gtk_list_set_selection_mode( GtkList *list,
+ GtkSelectionMode mode );
+</verb></tscreen>
- dial->old_value = adjustment->value;
- dial->old_lower = adjustment->lower;
- dial->old_upper = adjustment->upper;
- }
-}
+Set the selection mode MODE which can be of GTK_SELECTION_SINGLE,
+GTK_SELECTION_BROWSE, GTK_SELECTION_MULTIPLE or
+GTK_SELECTION_EXTENDED.
-static void
-gtk_dial_adjustment_value_changed (GtkAdjustment *adjustment,
- gpointer data)
-{
- GtkDial *dial;
+<tscreen><verb>
+GtkList *GTK_LIST( gpointer obj );
+</verb></tscreen>
- g_return_if_fail (adjustment != NULL);
- g_return_if_fail (data != NULL);
+Cast a generic pointer to `GtkList *'. *Note Standard Macros::, for
+more info.
- dial = GTK_DIAL (data);
+<tscreen><verb>
+GtkListClass *GTK_LIST_CLASS( gpointer class);
+</verb></tscreen>
- if (dial->old_value != adjustment->value)
- {
- gtk_dial_update (dial);
+Cast a generic pointer to `GtkListClass*'. *Note Standard Macros::,
+for more info.
- dial->old_value = adjustment->value;
- }
-}
-/* example-end */
+<tscreen><verb>
+gint GTK_IS_LIST( gpointer obj);
</verb></tscreen>
+Determine if a generic pointer refers to a `GtkList' object. *Note
+Standard Macros::, for more info.
+
<!-- ----------------------------------------------------------------- -->
-<sect1> Scribble
+<sect1> Example
<p>
+Following is an example program that will print out the changes of the
+selection of a GtkList, and lets you "arrest" list items into a prison
+by selecting them with the rightmost mouse button.
+
<tscreen><verb>
-/* example-start scribble-simple scribble-simple.c */
+/* example-start list list.c */
-/* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+/* Include the gtk+ header files
+ * Include stdio.h, we need that for the printf() function
*/
+#include <gtk/gtk.h>
+#include <stdio.h>
-#include <gtk/gtk.h>
-
-/* Backing pixmap for drawing area */
-static GdkPixmap *pixmap = NULL;
+/* This is our data identification string to store
+ * data in list items
+ */
+const gchar *list_item_data_key="list_item_data";
-/* Create a new backing pixmap of the appropriate size */
-static gint
-configure_event (GtkWidget *widget, GdkEventConfigure *event)
-{
- if (pixmap)
- gdk_pixmap_unref(pixmap);
- pixmap = gdk_pixmap_new(widget->window,
- widget->allocation.width,
- widget->allocation.height,
- -1);
- gdk_draw_rectangle (pixmap,
- widget->style->white_gc,
- TRUE,
- 0, 0,
- widget->allocation.width,
- widget->allocation.height);
+/* prototypes for signal handler that we are going to connect
+ * to the GtkList widget
+ */
+static void sigh_print_selection( GtkWidget *gtklist,
+ gpointer func_data);
- return TRUE;
-}
+static void sigh_button_event( GtkWidget *gtklist,
+ GdkEventButton *event,
+ GtkWidget *frame );
-/* Redraw the screen from the backing pixmap */
-static gint
-expose_event (GtkWidget *widget, GdkEventExpose *event)
-{
- gdk_draw_pixmap(widget->window,
- widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
- pixmap,
- event->area.x, event->area.y,
- event->area.x, event->area.y,
- event->area.width, event->area.height);
- return FALSE;
-}
+/* Main function to set up the user interface */
-/* Draw a rectangle on the screen */
-static void
-draw_brush (GtkWidget *widget, gdouble x, gdouble y)
-{
- GdkRectangle update_rect;
+gint main (int argc,
+ gchar *argv[])
+{
+ GtkWidget *separator;
+ GtkWidget *window;
+ GtkWidget *vbox;
+ GtkWidget *scrolled_window;
+ GtkWidget *frame;
+ GtkWidget *gtklist;
+ GtkWidget *button;
+ GtkWidget *list_item;
+ GList *dlist;
+ guint i;
+ gchar buffer[64];
+
+
+ /* Initialize gtk+ (and subsequently gdk) */
- update_rect.x = x - 5;
- update_rect.y = y - 5;
- update_rect.width = 10;
- update_rect.height = 10;
- gdk_draw_rectangle (pixmap,
- widget->style->black_gc,
- TRUE,
- update_rect.x, update_rect.y,
- update_rect.width, update_rect.height);
- gtk_widget_draw (widget, &update_rect);
+ gtk_init(&argc, &argv);
+
+
+ /* Create a window to put all the widgets in
+ * connect gtk_main_quit() to the "destroy" event of
+ * the window to handle window manager close-window-events
+ */
+ window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title(GTK_WINDOW(window), "GtkList Example");
+ gtk_signal_connect(GTK_OBJECT(window),
+ "destroy",
+ GTK_SIGNAL_FUNC(gtk_main_quit),
+ NULL);
+
+
+ /* Inside the window we need a box to arrange the widgets
+ * vertically */
+ vbox=gtk_vbox_new(FALSE, 5);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
+ gtk_container_add(GTK_CONTAINER(window), vbox);
+ gtk_widget_show(vbox);
+
+ /* This is the scrolled window to put the GtkList widget inside */
+ scrolled_window=gtk_scrolled_window_new(NULL, NULL);
+ gtk_widget_set_usize(scrolled_window, 250, 150);
+ gtk_container_add(GTK_CONTAINER(vbox), scrolled_window);
+ gtk_widget_show(scrolled_window);
+
+ /* Create the GtkList widget.
+ * Connect the sigh_print_selection() signal handler
+ * function to the "selection_changed" signal of the GtkList
+ * to print out the selected items each time the selection
+ * has changed */
+ gtklist=gtk_list_new();
+ gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW(scrolled_window),
+ gtklist);
+ gtk_widget_show(gtklist);
+ gtk_signal_connect(GTK_OBJECT(gtklist),
+ "selection_changed",
+ GTK_SIGNAL_FUNC(sigh_print_selection),
+ NULL);
+
+ /* We create a "Prison" to put a list item in ;) */
+ frame=gtk_frame_new("Prison");
+ gtk_widget_set_usize(frame, 200, 50);
+ gtk_container_set_border_width(GTK_CONTAINER(frame), 5);
+ gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
+ gtk_container_add(GTK_CONTAINER(vbox), frame);
+ gtk_widget_show(frame);
+
+ /* Connect the sigh_button_event() signal handler to the GtkList
+ * which will handle the "arresting" of list items
+ */
+ gtk_signal_connect(GTK_OBJECT(gtklist),
+ "button_release_event",
+ GTK_SIGNAL_FUNC(sigh_button_event),
+ frame);
+
+ /* Create a separator */
+ separator=gtk_hseparator_new();
+ gtk_container_add(GTK_CONTAINER(vbox), separator);
+ gtk_widget_show(separator);
+
+ /* Finally create a button and connect it's "clicked" signal
+ * to the destruction of the window */
+ button=gtk_button_new_with_label("Close");
+ gtk_container_add(GTK_CONTAINER(vbox), button);
+ gtk_widget_show(button);
+ gtk_signal_connect_object(GTK_OBJECT(button),
+ "clicked",
+ GTK_SIGNAL_FUNC(gtk_widget_destroy),
+ GTK_OBJECT(window));
+
+
+ /* Now we create 5 list items, each having it's own
+ * label and add them to the GtkList using gtk_container_add()
+ * Also we query the text string from the label and
+ * associate it with the list_item_data_key for each list item
+ */
+ for (i=0; i<5; i++) {
+ GtkWidget *label;
+ gchar *string;
+
+ sprintf(buffer, "ListItemContainer with Label #%d", i);
+ label=gtk_label_new(buffer);
+ list_item=gtk_list_item_new();
+ gtk_container_add(GTK_CONTAINER(list_item), label);
+ gtk_widget_show(label);
+ gtk_container_add(GTK_CONTAINER(gtklist), list_item);
+ gtk_widget_show(list_item);
+ gtk_label_get(GTK_LABEL(label), &string);
+ gtk_object_set_data(GTK_OBJECT(list_item),
+ list_item_data_key,
+ string);
+ }
+ /* Here, we are creating another 5 labels, this time
+ * we use gtk_list_item_new_with_label() for the creation
+ * we can't query the text string from the label because
+ * we don't have the labels pointer and therefore
+ * we just associate the list_item_data_key of each
+ * list item with the same text string.
+ * For adding of the list items we put them all into a doubly
+ * linked list (GList), and then add them by a single call to
+ * gtk_list_append_items().
+ * Because we use g_list_prepend() to put the items into the
+ * doubly linked list, their order will be descending (instead
+ * of ascending when using g_list_append())
+ */
+ dlist=NULL;
+ for (; i<10; i++) {
+ sprintf(buffer, "List Item with Label %d", i);
+ list_item=gtk_list_item_new_with_label(buffer);
+ dlist=g_list_prepend(dlist, list_item);
+ gtk_widget_show(list_item);
+ gtk_object_set_data(GTK_OBJECT(list_item),
+ list_item_data_key,
+ "ListItem with integrated Label");
+ }
+ gtk_list_append_items(GTK_LIST(gtklist), dlist);
+
+ /* Finally we want to see the window, don't we? ;) */
+ gtk_widget_show(window);
+
+ /* Fire up the main event loop of gtk */
+ gtk_main();
+
+ /* We get here after gtk_main_quit() has been called which
+ * happens if the main window gets destroyed
+ */
+ return(0);
}
-static gint
-button_press_event (GtkWidget *widget, GdkEventButton *event)
+/* This is the signal handler that got connected to button
+ * press/release events of the GtkList
+ */
+void sigh_button_event( GtkWidget *gtklist,
+ GdkEventButton *event,
+ GtkWidget *frame )
{
- if (event->button == 1 && pixmap != NULL)
- draw_brush (widget, event->x, event->y);
-
- return TRUE;
+ /* We only do something if the third (rightmost mouse button
+ * was released
+ */
+ if (event->type==GDK_BUTTON_RELEASE &&
+ event->button==3) {
+ GList *dlist, *free_list;
+ GtkWidget *new_prisoner;
+
+ /* Fetch the currently selected list item which
+ * will be our next prisoner ;)
+ */
+ dlist=GTK_LIST(gtklist)->selection;
+ if (dlist)
+ new_prisoner=GTK_WIDGET(dlist->data);
+ else
+ new_prisoner=NULL;
+
+ /* Look for already imprisoned list items, we
+ * will put them back into the list.
+ * Remember to free the doubly linked list that
+ * gtk_container_children() returns
+ */
+ dlist=gtk_container_children(GTK_CONTAINER(frame));
+ free_list=dlist;
+ while (dlist) {
+ GtkWidget *list_item;
+
+ list_item=dlist->data;
+
+ gtk_widget_reparent(list_item, gtklist);
+
+ dlist=dlist->next;
+ }
+ g_list_free(free_list);
+
+ /* If we have a new prisoner, remove him from the
+ * GtkList and put him into the frame "Prison".
+ * We need to unselect the item first.
+ */
+ if (new_prisoner) {
+ GList static_dlist;
+
+ static_dlist.data=new_prisoner;
+ static_dlist.next=NULL;
+ static_dlist.prev=NULL;
+
+ gtk_list_unselect_child(GTK_LIST(gtklist),
+ new_prisoner);
+ gtk_widget_reparent(new_prisoner, frame);
+ }
+ }
}
-static gint
-motion_notify_event (GtkWidget *widget, GdkEventMotion *event)
+/* This is the signal handler that gets called if GtkList
+ * emits the "selection_changed" signal
+ */
+void sigh_print_selection( GtkWidget *gtklist,
+ gpointer func_data)
{
- int x, y;
- GdkModifierType state;
-
- if (event->is_hint)
- gdk_window_get_pointer (event->window, &x, &y, &state);
- else
- {
- x = event->x;
- y = event->y;
- state = event->state;
+ GList *dlist;
+
+ /* Fetch the doubly linked list of selected items
+ * of the GtkList, remember to treat this as read-only!
+ */
+ dlist=GTK_LIST(gtklist)->selection;
+
+ /* If there are no selected items there is nothing more
+ * to do than just telling the user so
+ */
+ if (!dlist) {
+ g_print("Selection cleared\n");
+ return;
}
+ /* Ok, we got a selection and so we print it
+ */
+ g_print("The selection is a ");
- if (state & GDK_BUTTON1_MASK && pixmap != NULL)
- draw_brush (widget, x, y);
-
- return TRUE;
+ /* Get the list item from the doubly linked list
+ * and then query the data associated with list_item_data_key.
+ * We then just print it */
+ while (dlist) {
+ GtkObject *list_item;
+ gchar *item_data_string;
+
+ list_item=GTK_OBJECT(dlist->data);
+ item_data_string=gtk_object_get_data(list_item,
+ list_item_data_key);
+ g_print("%s ", item_data_string);
+
+ dlist=dlist->next;
+ }
+ g_print("\n");
}
+/* example-end */
+</verb></tscreen>
-void
-quit ()
-{
- gtk_exit (0);
-}
+<!-- ----------------------------------------------------------------- -->
+<sect1> List Item Widget
+<p>
+The GtkListItem widget is designed to act as a container holding up to
+one child, providing functions for selection/deselection just like the
+GtkList widget requires them for its children.
-int
-main (int argc, char *argv[])
-{
- GtkWidget *window;
- GtkWidget *drawing_area;
- GtkWidget *vbox;
+A GtkListItem has its own window to receive events and has its own
+background color which is usually white.
- GtkWidget *button;
+As it is directly derived from a GtkItem it can be treated as such by
+using the GTK_ITEM(ListItem) macro, see the GtkItem widget for more on
+this. Usually a GtkListItem just holds a label to identify e.g. a
+filename within a GtkList -- therefore the convenience function
+gtk_list_item_new_with_label() is provided. The same effect can be
+achieved by creating a GtkLabel on its own, setting its alignment to
+xalign=0 and yalign=0.5 with a subsequent container addition to the
+GtkListItem.
- gtk_init (&argc, &argv);
+As one is not forced to add a GtkLabel to a GtkListItem, you could
+also add a GtkVBox or a GtkArrow etc. to the GtkListItem.
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_widget_set_name (window, "Test Input");
+<!-- ----------------------------------------------------------------- -->
+<sect1> Signals
+<p>
+A GtkListItem does not create new signals on its own, but inherits
+the signals of a GtkItem. *Note GtkItem::, for more info.
- vbox = gtk_vbox_new (FALSE, 0);
- gtk_container_add (GTK_CONTAINER (window), vbox);
- gtk_widget_show (vbox);
+<!-- ----------------------------------------------------------------- -->
+<sect1> Functions
+<p>
+<tscreen><verb>
+guint gtk_list_item_get_type( void );
+</verb></tscreen>
- gtk_signal_connect (GTK_OBJECT (window), "destroy",
- GTK_SIGNAL_FUNC (quit), NULL);
+Returns the `GtkListItem' type identifier.
- /* Create the drawing area */
+<tscreen><verb>
+GtkWidget *gtk_list_item_new( void );
+</verb></tscreen>
- drawing_area = gtk_drawing_area_new ();
- gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);
- gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
+Create a new GtkListItem object. The new widget is returned as a
+pointer to a GtkWidget object. NULL is returned on failure.
- gtk_widget_show (drawing_area);
+<tscreen><verb>
+GtkWidget *gtk_list_item_new_with_label( gchar *label );
+</verb></tscreen>
- /* Signals used to handle backing pixmap */
+Create a new GtkListItem object, having a single GtkLabel as the sole
+child. The new widget is returned as a pointer to a GtkWidget
+object. NULL is returned on failure.
- gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
- (GtkSignalFunc) expose_event, NULL);
- gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
- (GtkSignalFunc) configure_event, NULL);
+<tscreen><verb>
+void gtk_list_item_select( GtkListItem *list_item );
+</verb></tscreen>
- /* Event signals */
+This function is basically a wrapper around a call to gtk_item_select
+(GTK_ITEM (list_item)) which will emit the select signal. *Note
+GtkItem::, for more info.
- gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
- (GtkSignalFunc) motion_notify_event, NULL);
- gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
- (GtkSignalFunc) button_press_event, NULL);
+<tscreen><verb>
+void gtk_list_item_deselect( GtkListItem *list_item );
+</verb></tscreen>
- gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
- | GDK_LEAVE_NOTIFY_MASK
- | GDK_BUTTON_PRESS_MASK
- | GDK_POINTER_MOTION_MASK
- | GDK_POINTER_MOTION_HINT_MASK);
+This function is basically a wrapper around a call to
+gtk_item_deselect (GTK_ITEM (list_item)) which will emit the deselect
+signal. *Note GtkItem::, for more info.
- /* .. And a quit button */
- button = gtk_button_new_with_label ("Quit");
- gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+<tscreen><verb>
+GtkListItem *GTK_LIST_ITEM( gpointer obj );
+</verb></tscreen>
- gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
- GTK_SIGNAL_FUNC (gtk_widget_destroy),
- GTK_OBJECT (window));
- gtk_widget_show (button);
+Cast a generic pointer to `GtkListItem*'. *Note Standard Macros::, for
+more info.
- gtk_widget_show (window);
+<tscreen><verb>
+GtkListItemClass *GTK_LIST_ITEM_CLASS( gpointer class );
+</verb></tscreen>
- gtk_main ();
+Cast a generic pointer to GtkListItemClass*. *Note Standard Macros::,
+for more info.
- return 0;
-}
-/* example-end */
+<tscreen><verb>
+gint GTK_IS_LIST_ITEM( gpointer obj );
</verb></tscreen>
+Determine if a generic pointer refers to a `GtkListItem' object.
+*Note Standard Macros::, for more info.
+
+<!-- ----------------------------------------------------------------- -->
+<sect1> Example
+<p>
+Please see the GtkList example on this, which covers the usage of a
+GtkListItem as well.
+
+
</article>